hapcryst-0.2.0/0000755000175100017510000000000015160525022012752 5ustar runnerrunnerhapcryst-0.2.0/Makefile0000644000175100017510000000041415160525022014411 0ustar runnerrunner.PHONY: doc html clean check GAP ?= gap GAP_ARGS = -q --quitonbreak --packagedirs $(abspath .) doc: $(GAP) $(GAP_ARGS) makedoc.g -c 'QUIT;' html: NOPDF=1 $(GAP) $(GAP_ARGS) makedoc.g -c 'QUIT;' clean: cd doc && ./clean check: $(GAP) $(GAP_ARGS) tst/testall.g hapcryst-0.2.0/README.md0000644000175100017510000000727115160525022014240 0ustar runnerrunner[![CI](https://github.com/gap-packages/hapcryst/actions/workflows/CI.yml/badge.svg)](https://github.com/gap-packages/hapcryst/actions/workflows/CI.yml) [![Code Coverage](https://codecov.io/github/gap-packages/hapcryst/coverage.svg?branch=master&token=)](https://codecov.io/gh/gap-packages/hapcryst) # HAPcryst A GAP4 extension for HAP calculating resolutions for Bieberbach groups. Copyright (C) Marc Roeder 2007-2008 Marc Roeder NUI Galway, Ireland This package is an add-on for Graham Ellis' HAP package. HAPcryst implements some functions for crystallographic groups, namely OrbitStabilizer-type methods. It is also capable of calculating free resolutions for Bieberbach groups. HAPcryst is distributed under the terms of the GNU General Public License version 2.0 or later. See [LICENSE](LICENSE) for the text of version 2, or visit . Please send bug reports to . ## Installation HAPcryst depends on the following packages: - `hap` (as HAPcryst is an extension of HAP) - `polymaking` (which in turn depends on external software) - `Cryst` HAPcryst will not load if you do not have a recent version of those packages installed. The following packages are not required but suggested: - `Carat` - `CrystCat` - `GAPDoc` 1. Download the package archive `HAPcryst.tar.bz2`, `HAPcryst.tar.gz`, or `HAPcryst-win.zip` (where `` is some version number) to the `pkg/` directory of the GAP home directory. If you do not have permission to do so, create a directory called `gap/pkg` in your home directory. 2. Change directory to `pkg/` and unpack the archive using the corresponding command: ```sh tar -xjf HAPcryst.tar.bz2 tar -xzf HAPcryst.tar.gz unzip HAPcryst-win.zip ``` Replace `` with the version number. 3. Start GAP. If you have created the directory `gap/pkg` in your home directory, use `gap -l '/gap;'` where `` is the path of your home directory. Use `pwd` to find out what it is if you do not know. 4. Call GAP and type `LoadPackage("hapcryst");` to load HAPcryst. If GAP returns some error messages, load `hap`. 5. Run the test file by calling `ReadPackage("hapcryst","tst/testall.g");`. ## Recommendation Calculating resolutions of Bieberbach groups involves convex hull computations. `polymake` by default uses `cdd` to compute convex hulls. Experiments suggest that `lrs` is the more suitable algorithm for the convex hull computations done in HAPcryst than the standard `cdd`. You can change the behaviour of `polymake` by editing the file `/.polymake/prefer.pl`. It should contain a section like this; just make sure `lrs` is before `cdd`. The position of `beneath_beyond` does not matter. ```text application polytope; prefer "*.convex_hull lrs, beneath_beyond, cdd"; ``` ## Documentation The documentation of the package can be found in the `doc/` subdirectory. A second part of the documentation describes datatypes used in HAPcryst. This can be found in the `lib/datatypes/doc` subdirectory of the HAPcryst main directory. ## Examples The `examples` directory contains code that generates pictures (JavaView applets) of Dirichlet domains of 3-dimensional Bieberbach groups with coloured orbits of the group acting on the faces of the tessellation of `R^3`. ```text gap> ReadPackage("hapcryst","examples/3dimBieberbachFD.gap"); gap> viewFundamentalDomain([0,0,0],1); ``` For instructions, see `examples/3dimBieberbacFD.gap` in the hapcryst package tree. The functions will also generate pictures of Dirichlet domains for non-Bieberbach groups, but the orientation of the shown edges does not necessarily make sense any more. hapcryst-0.2.0/read.g0000644000175100017510000000173215160525022014040 0ustar runnerrunnerReadPackage("HAPcryst","lib/environment.gi"); ### ####### a few things about datatypes and conversion ####### aka. "the nerdy stuff" ### ReadPackage("HAPcryst","lib/GroupRing.gi"); ReadPackage("HAPcryst","lib/datatypes/resolutionAccess_generic.gi"); ReadPackage("HAPcryst","lib/datatypes/resolutionAccess_GroupRing.gi"); ReadPackage("HAPcryst","lib/CWcomplexThings.gi"); ReadPackage("HAPcryst","lib/CWcomplexThings_GroupRingRep.gi"); ######## ReadPackage("HAPcryst","lib/misc.gi"); ReadPackage("HAPcryst","lib/spacegroups.gi"); ReadPackage("HAPcryst","lib/translations.gi"); ReadPackage("HAPcryst","lib/geometry.gi"); #ReadPackage("HAPcryst","lib/PartialHasseDiagramByGroup.gi"); ReadPackage("HAPcryst","lib/FaceLatticeAndBoundaryBieberbachGroup.gi"); ReadPackage("HAPcryst","lib/resolutionBieberbach.gi"); ReadPackage("HAPcryst","lib/FundamentalDomain.gi"); ReadPackage("HAPcryst","lib/FundamentalDomainStandardSP.gi"); ReadPackage("HAPcryst","lib/FundamentalDomainBieberbach.gi"); hapcryst-0.2.0/lib/0000755000175100017510000000000015160525022013520 5ustar runnerrunnerhapcryst-0.2.0/lib/geometry.gi0000644000175100017510000000640315160525022015677 0ustar runnerrunner############################################################################# ## #W geometry.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## # for two pairs, generate the inequality of the half-space "bewteen" them. ############## InstallMethod(BisectorInequalityFromPointPair, [IsVector,IsVector,IsMatrix], function(center,point,gram) local centergram, pointgram, inequality; if center=point then return fail; fi; centergram:=center*gram; pointgram:=point*gram; inequality:=Concatenation([-centergram*center+pointgram*point],2*(centergram-pointgram)); return inequality; end); # Again, for the standard scalar product: InstallMethod(BisectorInequalityFromPointPair, [IsVector,IsVector], function(center,point) local centergram, centernorm, pointgram, inequality; if center=point then return fail; fi; inequality:=Concatenation([-center^2+point^2],2*(center-point)); return inequality; end); ############################## InstallMethod(WhichSideOfHyperplane, [IsVector,IsVector], function(vector,inequality) local size, eval; size:=Size(inequality); if not Size(vector)+1=size then Error(" and must be given by a vector."); fi; if not ForAll(Union(vector,inequality),IsRat) then Error("This does only work for rational vector spaces"); fi; return WhichSideOfHyperplaneNC(vector,inequality); end); InstallMethod(WhichSideOfHyperplaneNC, [IsVector,IsVector], function(vector,inequality) local eval; eval:=vector*inequality{[2..Size(inequality)]}+inequality[1]; if eval>0 then return 1; elif eval<0 then return -1; else return 0; fi; end); ######################################## InstallMethod(RelativePositionPointAndPolygon, [IsVector,IsPolymakeObject], function(point,poly) local facetpositions, facet, side; if point in Polymake(poly,"VERTICES") then return "VERTEX"; fi; if Polymake(poly,"DIM")=0 then return "OUTSIDE"; fi; facetpositions:=[]; for facet in Polymake(poly,"FACETS") do side:=WhichSideOfHyperplane(point,facet); if side=-1 then return "OUTSIDE"; else AddSet(facetpositions,side); fi; od; if facetpositions=[1] then return "INSIDE"; else return "FACET"; fi; end); hapcryst-0.2.0/lib/spacegroups.gi0000644000175100017510000005176215160525022016407 0ustar runnerrunner############################################################################# ## #W spacegroups.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## InstallMethod(PointGroupRepresentatives,"for crystallographic groups on right", [IsAffineCrystGroupOnLeftOrRight], function(group) local linearPart, walkthetreeright, walkthetreeleft, generators, dim, affinepointgroupels, pointgroupels; ########## # local methods for fast access to translational and linear part: # linearPart:=function(mat) return mat{[1..dim-1]}{[1..dim-1]}; end; ########## # A recursive method to generate representatives for the point group. # This also finds a translation basis. # Note that the results are stored in global (not belonging to # "walkthetree") variables. # walkthetreeright:=function(element,gens) local g, endofbranch, newel, newellin, differences, newtrans; for g in gens do newel:=element*g; newellin:=linearPart(newel); if not (newellin in pointgroupels) then AddSet(affinepointgroupels,newel); AddSet(pointgroupels,newellin); walkthetreeright(newel,gens); fi; od; end; walkthetreeleft:=function(element,gens) local g, endofbranch, newel, newellin, differences, newtrans; for g in gens do newel:=g*element; newellin:=linearPart(newel); if not (newellin in pointgroupels) then AddSet(affinepointgroupels,newel); AddSet(pointgroupels,newellin); walkthetreeleft(newel,gens); fi; od; end; ########## #And here is the main program: # generators:=GeneratorsOfGroup(group); dim:=DimensionOfMatrixGroup(group); ########## # Now generate the pointgroup and representatives for it. # affinepointgroupels:=[IdentityMat(dim)]; pointgroupels:=[IdentityMat(dim-1)]; if IsAffineCrystGroupOnRight(group) then walkthetreeright(generators[1]^0,generators); if not Size(PointGroup(AffineCrystGroupOnRight(generators)))=Size(affinepointgroupels) then Error("generation of point group failed!"); fi; else walkthetreeleft(generators[1]^0,generators); if not Size(PointGroup(AffineCrystGroupOnLeft(generators)))=Size(affinepointgroupels) then Error("generation of point group failed!"); fi; fi; return Set(affinepointgroupels); end); ############################################################################# # # Let $S$ be an $n$-dimensional crystallographic group in standard form. # For a given point $x$ in $[0,1]^n$, we determine the stabilizer in $S$ # and the part of the orbit which lies inside $[0,1]^n$. # # If the linear part of the group elements are orthogonal with respect to # the euclidian scalar product, all elements of the orbit lying in $[-1,1]^n$ # (and a few more) are returned. In all other cases, this is not guaranteed. # InstallMethod(OrbitStabilizerInUnitCubeOnRight,"for space groups on right", [IsGroup,IsVector], function(group,x) local orbitpart, stabilizer, xaff, pointgroupreps, g, imageaff, image, translation; if not IsAffineCrystGroupOnRight(group) and IsStandardSpaceGroup(group) then Error("Group must be an AffineCrystGroupOnRight in standard form"); fi; orbitpart:=[]; stabilizer:=[]; if not VectorModOne(x)=x then Error("please choose a vector from [0,1)^n"); fi; xaff:=Concatenation(x,[1]); Add(orbitpart,x); pointgroupreps:=PointGroupRepresentatives(group); for g in pointgroupreps do imageaff:=xaff*g; image:=VectorModOne(imageaff){[1..Size(imageaff)-1]}; if not image in orbitpart then AddSet(orbitpart,image); elif imageaff=xaff then Add(stabilizer,g); elif image=x then translation:=IdentityMat(Size(xaff)); translation[Size(translation)]:=-imageaff+xaff; translation[Size(translation)][Size(translation)]:=1; Add(stabilizer,g*translation); fi; od; return rec(orbit:=orbitpart,stabilizer:=Subgroup(group,stabilizer)); end); ############################################################################# ## #O OrbitStabilzerInUniCubeOnRightOnSets(group,set) ## InstallMethod(OrbitStabilizerInUnitCubeOnRightOnSets, "for space groups on right", [IsGroup,IsDenseList], function(group,set) local dim, stepsFromZeroOne, orbitpart, stabilizer, setaff, pointgroupreps, g, imageaff, point, transvector, image; if not IsStandardSpaceGroup(group) and IsAffineCrystGroupOnRight(group) then Error("group must be a StandardSpaceGroup acting on right"); fi; dim:=DimensionOfMatrixGroup(group); if not Set(set,VectorModOne)=set or not Set(set,Size)=[dim-1] then Error("please choose a set of vectors from [0,1)^n"); fi; if not IsSet(set) and ForAll(set,IsVector) then Error("set must be a Set of Vectors"); fi; stepsFromZeroOne:=function(q) local r; r:=Int(q); if q<0 then return r-1; else return r; fi; end; orbitpart:=[]; stabilizer:=[]; setaff:=Set(set,x->Concatenation(x,[1])); Add(orbitpart,set); pointgroupreps:=PointGroupRepresentatives(group); for g in pointgroupreps do imageaff:=Set(setaff,s->s*g); if imageaff=setaff then Add(stabilizer,g); fi; for point in imageaff do transvector:=List(point{[1..Size(point)-1]}, i->stepsFromZeroOne(i)); image:=Set(imageaff,i->i{[1..Size(point)-1]}-transvector); if not image in orbitpart then AddSet(orbitpart,image); elif image=set then Add(stabilizer,g*TranslationOnRightFromVector(-transvector)); fi; od; od; return rec(orbit:=orbitpart,stabilizer:=Group(stabilizer)); end); ############################################################################# ## #O OrbitPartInVertexSetsStandardSpaceGroup ## # And a special function not only for polyhedrae: #this takes a list of vertices (vectors) and returns the part of the # orbit which consists of vertex sets. # # This doesn't even use that the vertices are all in [-1,1]. # It just works for arbitray polyhedra. # # works better for small than for large. # InstallMethod(OrbitPartInVertexSetsStandardSpaceGroup, [IsGroup,IsDenseList,IsDenseList], function(group,vertexset,allvertices) local orbit, dim, pointGroupReps, setaff, newimagesize, newimage, g, image, point, trans, index, stillinvertices; if not IsStandardSpaceGroup(group) or not IsAffineCrystGroupOnRight(group) then TryNextMethod(); fi; if not (IsSet(vertexset) and IsMatrix(vertexset) and IsSet(allvertices) and IsSubset(allvertices,vertexset)) then Error(" must be a subset of which must be a set of vectors"); fi; dim:=Size(allvertices[1]); orbit:=[vertexset]; pointGroupReps:=PointGroupRepresentatives(group); setaff:=Set(vertexset,x->Concatenation(x,[1])); newimagesize:=Size(setaff); newimage:=[1..newimagesize]; for g in pointGroupReps do # imageaff:=Set(setaff,s->s*g); image:=Set(setaff*g,i->i{[1..dim]}); point:=image[1];#{[1..dim]}; for trans in allvertices-point do if ForAll(trans,IsInt) then index:=1; stillinvertices:=true; while index<=newimagesize and stillinvertices do newimage[index]:=image[index]+trans; if not newimage[index] in allvertices then stillinvertices:=false; fi; index:=index+1; od; if stillinvertices then Add(orbit,Set(newimage)); fi; fi; od; od; return Set(orbit); end); ############################################################################# ## #O OrbitPartInFacesStandardSpaceGroup ## # And a special function not only for polyhedrae: # this takes a set of vertices (vectors) and returns the part of the # part of the orrbit lying inside a set of sets of vectors. # This works like OnSets, but does only return a part of the orbit. # has to be an element of # # This doesn't even use that the vertices are all in [-1,1]. # It just works for arbitray polyhedra. # # works better for small than for large. # InstallMethod(OrbitPartInFacesStandardSpaceGroup, [IsGroup,IsDenseList,IsDenseList], function(group,vertexset,faceset) local allvertices, currentfirst, facesbyfirstvertex, currentfirstposition, face, i, dim, orbit, pointGroupReps, setaff, newimagesize, g, image, point, targetbatch, trans, index, thereisaface, candidatefaces, newimage, newentry; if not IsStandardSpaceGroup(group) or not IsAffineCrystGroupOnRight(group) then TryNextMethod(); fi; if not (IsSet(vertexset) and IsSet(faceset) and ForAll(faceset,IsSet) and vertexset in faceset and IsMatrix(vertexset)) then Error(" must be an element of which must be a set of sets of vectors"); fi; # all vertices that turn up in a given position in any face: # and all faces partitioned by there first element. # allvertices:=List([1..Maximum(List(faceset,Size))],i->[]); currentfirst:=[]; facesbyfirstvertex:=[]; currentfirstposition:=0; for face in faceset do for i in [1..Size(face)] do Add(allvertices[i],face[i]); if i=1 then if currentfirst=face[1] then Add(facesbyfirstvertex[currentfirstposition],face); else currentfirst:=face[1]; currentfirstposition:=currentfirstposition+1; facesbyfirstvertex[currentfirstposition]:=[face]; fi; fi; od; od; Apply(allvertices,Set); MakeImmutable(allvertices); dim:=Size(faceset[1][1]); orbit:=[]; pointGroupReps:=Set(PointGroupRepresentatives(group)); setaff:=List(vertexset,x->Concatenation(x,[1])); newimagesize:=Size(setaff); for g in pointGroupReps do image:=Set(setaff*g,i->i{[1..dim]}); point:=image[1]; #+trans has to be the smallest vector in the image set: for targetbatch in facesbyfirstvertex do trans:=targetbatch[1][1]-point; if ForAll(trans,IsInt) then index:=1; thereisaface:=true; candidatefaces:=targetbatch; newimage:=[targetbatch[1][1]]; while index<=newimagesize and thereisaface do newentry:=image[index]+trans; newimage[index]:=newentry; if not newentry in allvertices[index] then thereisaface:=false; else candidatefaces:=Filtered(candidatefaces,c->c[index]=newentry); index:=index+1; fi; if candidatefaces=[] then thereisaface:=false; fi; od; if thereisaface then Add(orbit,newimage); fi; fi; od; od; return Set(orbit); end); ############################################################################# ## #O OrbitPartAndRepresentativesInFacesStandardSpaceGroup ## # And a special function not only for polyhedrae: # this takes a set of vertices (vectors) and returns the part of the # part of the orrbit lying inside a set of sets of vectors. # This works like OnSets, but does only return a part of the orbit. # has to be an element of . # # This doesn't even use that the vertices are all in [-1,1]. # It just works for arbitray polyhedra. # # works better for small than for large. # # the output is a list of pairs, the first entry of each pair is an orbit # element and the second one a representative taking to that # orbit element. # InstallMethod(OrbitPartAndRepresentativesInFacesStandardSpaceGroup, [IsGroup,IsDenseList,IsDenseList], function(group,vertexset,faceset) local allvertices, currentfirst, facesbyfirstvertex, currentfirstposition, face, i, dim, orbit, reps, pointGroupReps, setaff, newimagesize, g, image, point, targetbatch, trans, index, thereisaface, candidatefaces, newimage, newentry, representative; if not IsStandardSpaceGroup(group) or not IsAffineCrystGroupOnRight(group) then TryNextMethod(); fi; if not (IsSet(vertexset) and IsSet(faceset) and ForAll(faceset,IsSet) and vertexset in faceset and IsMatrix(vertexset)) then Error(" must be an element of which must be a set of sets of vectors"); fi; # all vertices that turn up in a given position in any face: # and all faces partitioned by there first element. # allvertices:=List([1..Maximum(List(faceset,Size))],i->[]); currentfirst:=[]; facesbyfirstvertex:=[]; currentfirstposition:=0; for face in faceset do for i in [1..Size(face)] do Add(allvertices[i],face[i]); if i=1 then if currentfirst=face[1] then Add(facesbyfirstvertex[currentfirstposition],face); else currentfirst:=face[1]; currentfirstposition:=currentfirstposition+1; facesbyfirstvertex[currentfirstposition]:=[face]; fi; fi; od; od; Apply(allvertices,Set); MakeImmutable(allvertices); dim:=Size(faceset[1][1]); orbit:=[]; reps:=[]; pointGroupReps:=Set(PointGroupRepresentatives(group)); setaff:=List(vertexset,x->Concatenation(x,[1])); newimagesize:=Size(setaff); for g in pointGroupReps do image:=Set(setaff*g,i->i{[1..dim]}); point:=image[1]; #+trans has to be the smallest vector in the image set: for targetbatch in facesbyfirstvertex do trans:=targetbatch[1][1]-point; if ForAll(trans,IsInt) then index:=2; thereisaface:=true; candidatefaces:=targetbatch; newimage:=[targetbatch[1][1]]; while index<=newimagesize and thereisaface do newentry:=image[index]+trans; newimage[index]:=newentry; if not newentry in allvertices[index] then thereisaface:=false; else candidatefaces:=Filtered(candidatefaces,c->c[index]=newentry); index:=index+1; fi; if candidatefaces=[] then thereisaface:=false; fi; od; if thereisaface then if not newimage in orbit then representative:=ShallowCopy(g); representative[dim+1]:=representative[dim+1]+trans; Add(orbit,newimage); Add(reps,representative); SortParallel(orbit,reps); fi; fi; fi; od; od; return List([1..Size(orbit)],i->[orbit[i],reps[i]]); end); ############################################################################# ## #O StabilizerOnSetsStandardSpaceGroup ## ## InstallMethod(StabilizerOnSetsStandardSpaceGroup, [IsGroup,IsDenseList], function(group,set) local pointGroupReps, dim, stabgens, setaff, representative, alpha, image, trans, addel; if not (IsStandardSpaceGroup(group) and IsAffineCrystGroupOnRight(group)) then TryNextMethod(); fi; pointGroupReps:=PointGroupRepresentatives(group); if not IsSet(set) and IsMatrix(set) then Error(" must be a set of vectors"); fi; dim:=Size(set[1]); if not dim=DimensionOfMatrixGroup(group)-1 then Error("group and vectors don't fit"); fi; stabgens:=[]; setaff:=List(set,x->Concatenation(x,[1])); representative:=setaff[1]; for alpha in pointGroupReps do image:=Set(setaff,i->i*alpha); trans:=image[1]-representative; if ForAll(trans,IsInt) then if image=setaff+trans then addel:=MutableCopyMat(alpha); addel[dim+1]:=addel[dim+1]-trans; Add(stabgens,addel); fi; fi; od; return Group(Set(stabgens)); end); ############################################################################# ## #O RepresentativeActionOnRightOnSets(group,set,imageset) for StandardSpaceGroups ## InstallMethod(RepresentativeActionOnRightOnSets,"for crystallographic groups on right", [IsGroup,IsDenseList,IsDenseList], function(group,set, imageset) local dim, pointgroupreps, setaff, imagesetaff, imagepoint, g, setaffimage, point, difference, candidate; if not IsStandardSpaceGroup(group) and IsAffineCrystGroupOnRight(group) then Error("group must be a StandardSpaceGroup acting on right"); fi; dim:=DimensionOfMatrixGroup(group)-1; if not ForAll([set,imageset],IsSet) or set=[] or imageset=[] or Size(set)<>Size(imageset) then Error("set and imageset must be propper non empty sets of the same size"); fi; if not Set(set,Size)=[dim] or not Size(set)=Size(imageset) or not Set(imageset,Size)=[dim] or not ForAll(set,IsVector) or not ForAll(imageset,IsVector) then Error(" and must be sets of vectors of the right length"); fi; pointgroupreps:=PointGroupRepresentatives(group); setaff:=List(set,x->Concatenation(x,[1])); imagesetaff:=List(imageset,x->Concatenation(x,[1])); imagepoint:=imagesetaff[1]; for g in pointgroupreps do setaffimage:=List(setaff,s->s*g); difference:=imagepoint-Minimum(setaffimage); if ForAll(difference,IsInt) then if ForAll(setaffimage,i->i+difference in imagesetaff) then candidate:=ShallowCopy(g); candidate[dim+1]:=candidate[dim+1]+difference; return candidate; fi; fi; od; return fail; end); ############################################################################# ## #O GramianOfAverageScalarProductFiniteMatrixGroup ## # Suppose $G$ is a finite group of matrices. Suppose further, that you # know they are orthogonal with respect to (some) euclidian scalar product. # This method finds a Gramian matrix describing a positive definite symmetric # bilinear form. # This form isn't necessrily normed. But the gramian matrix has only # rational entries. # # The returned gramian matrix is that of the average scalar product induced # by $G$. # InstallMethod(GramianOfAverageScalarProductFromFiniteMatrixGroup, [IsGroup], function(group) local dim, basis, summands, g, gramian, i, j, denom; if not IsFinite(group) then Error("this only works for finite groups"); fi; dim:=Size(Representative(group)); basis:=IdentityMat(dim); if ForAll(GeneratorsOfGroup(group),g->TransposedMat(g)=Inverse(g)) then gramian:=basis; else summands:=Set(group,i->i*TransposedMat(i)); gramian:=Sum(summands); fi; return gramian; end); hapcryst-0.2.0/lib/environment.gi0000644000175100017510000000166715160525022016417 0ustar runnerrunner############################################################################# ## #W environment.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## SetInfoLevel(InfoHAPcryst,1); hapcryst-0.2.0/lib/CWcomplexThings_GroupRingRep.gd0000644000175100017510000001162015160525022021555 0ustar runnerrunner############################################################################# ## #W CWcomplexThings_GroupRingRep.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## DeclareOperation("UndirectedWord_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList]); DeclareOperation("UndirectedWordNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList]); DeclareOperation("IsUndirectedWord_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList]); DeclareOperation("IsUndirectedWord_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("OneCoefficientPartOfWordNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsVector]); DeclareOperation("OneCoefficientPartOfWord_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsVector]); DeclareOperation("IntersectingUndirectedWords_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList,IsDenseList]); DeclareOperation("IntersectingUndirectedWordsNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList,IsDenseList]); DeclareOperation("IsUndirectedSubWord_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList,IsDenseList]); DeclareOperation("IsUndirectedSubWordNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList,IsDenseList]); DeclareOperation("UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep",[IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("UndirectedBoundaryOfFreeZGLetter_LargeGroupRep",[IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); #DeclareOperation("UndirectedBoundaryOfFreeZGWord", # [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("UndirectedBoundaryOfFreeZGWordNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("UndirectedBoundaryOfFreeZGWord_LargeGroupRep",[IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("LowerSpaceFromWord_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList]); #DeclareOperation("SubspaceListFromWord", # [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("SubspaceListFromWordNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("SubspaceListFromWord_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("IsConnectedWordNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); #DeclareOperation("IsConnectedWord", # [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); #DeclareOperation("ConnectingPath", # [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList]); DeclareOperation("ConnectingPathNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList]); DeclareOperation("ConnectingPath_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList]); #DeclareOperation("IsContractibleWord", # [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("IsContractibleWordNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); #DeclareOperation("IsContractiblePartialSpace", # [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("IsContractiblePartialSpaceNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); #DeclareOperation("SphereContainingCell", # [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList]); DeclareOperation("SphereContainingCell_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList]); DeclareOperation("SphereContainingCellNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList]); #DeclareOperation("ChainComplexFromWord", # [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("ChainComplexFromWordNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("ChainComplexFromPartialSpace_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList]); DeclareOperation("ChainComplexFromPartialSpaceNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList]); hapcryst-0.2.0/lib/spacegroups.gd0000644000175100017510000000333415160525022016372 0ustar runnerrunner############################################################################# ## #W spacegroups.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## DeclareAttribute("PointGroupRepresentatives",IsAffineCrystGroupOnLeftOrRight); DeclareOperation("OrbitStabilizerInUnitCubeOnRight",[IsGroup,IsVector]); DeclareOperation("OrbitStabilizerInUnitCubeOnRightOnSets",[IsGroup,IsDenseList]); DeclareOperation("OrbitPartInVertexSetsStandardSpaceGroup", [IsGroup,IsDenseList,IsDenseList]); DeclareOperation("OrbitPartInFacesStandardSpaceGroup", [IsGroup,IsDenseList,IsDenseList]); DeclareOperation("OrbitPartAndRepresentativesInFacesStandardSpaceGroup", [IsGroup,IsDenseList,IsDenseList]); DeclareOperation("StabilizerOnSetsStandardSpaceGroup", [IsGroup,IsDenseList]); DeclareOperation("RepresentativeActionOnRightOnSets", [IsGroup,IsDenseList,IsDenseList]); DeclareOperation("GramianOfAverageScalarProductFromFiniteMatrixGroup", [IsGroup]); hapcryst-0.2.0/lib/CWcomplexThings.gd0000644000175100017510000000541715160525022017121 0ustar runnerrunner############################################################################# ## #W CWcomplexThings.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## DeclareOperation("UndirectedBoundaryOfFreeZGLetterNC",[IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("UndirectedBoundaryOfFreeZGLetter",[IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("UndirectedBoundaryOfFreeZGWordNC",[IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("UndirectedBoundaryOfFreeZGWord",[IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("SubspaceListFromWordNC", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("SubspaceListFromWord", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("IsConnectedWordNC", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("IsConnectedWord", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("ConnectingPathNC", [IsHapResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList]); DeclareOperation("ConnectingPath", [IsHapResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList]); DeclareOperation("IsContractibleWord", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("IsContractibleWordNC", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("SphereContainingCell", [IsHapResolutionRep,IsInt,IsDenseList,IsDenseList]); DeclareOperation("SphereContainingCellNC", [IsHapResolutionRep,IsInt,IsDenseList,IsDenseList]); DeclareOperation("ChainComplexFromWord", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("ChainComplexFromWordNC", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("IsContractiblePartialSpace", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("IsContractiblePartialSpaceNC", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("ChainComplexFromPartialSpace", [IsHapResolutionRep,IsDenseList]); DeclareOperation("ChainComplexFromPartialSpaceNC", [IsHapResolutionRep,IsDenseList]); hapcryst-0.2.0/lib/translations.gi0000644000175100017510000000704015160525022016563 0ustar runnerrunner############################################################################# ## #W translations.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## #O TranslationsToBox ## InstallMethod(TranslationsToBox,[IsVector,IsDenseList], function(point,box) local nextint,prevint, difference, entry, isinbox, coord; nextint:=function(x) if IsInt(x) then return x; elif x<0 then return Int(x); else return Int(x)+1; fi; end; prevint:=function(x) if IsInt(x) then return x; elif x<0 then return Int(x)-1; else return Int(x); fi; end; if not ForAll(box, IsVector) and ForAll(box,i->Size(i)=2) then Error("Box must be given as a list of pairs"); elif not ForAll(box,i->i[2]>i[1]) then Error("Box must not be empty"); fi; difference:=[]; for entry in [1..Size(point)] do coord:=point[entry]; difference[entry]:=[nextint(box[entry][1]-coord)..prevint(box[entry][2]-coord)]; od; return Cartesian(difference); end); ############################################################################# ## #O ShiftedOrbitPart ## InstallMethod(ShiftedOrbitPart, [IsVector,IsDenseList], function(point,orbitpart) local shiftedPoint; shiftedPoint:=function(x) local returnpoint, i, difference; returnpoint:=ShallowCopy(x); for i in[1..Size(x)] do returnpoint[i]:=x[i]-Int(x[i]); if AbsoluteValue(returnpoint[i])>1/2 then returnpoint[i]:=returnpoint[i]+SignRat(returnpoint[i]); elif returnpoint[i]=-1/2 then returnpoint[i]:=1/2; fi; od; return returnpoint; end; return Set(orbitpart-point,x->shiftedPoint(x))+point; end); ############################################################################# ## #O TranslationsToOneCubeAroundCenter ## ## And here are the translations taking the point to the cube around the point ##
## InstallMethod(TranslationsToOneCubeAroundCenter,[IsVector,IsVector], function(point,center) local returnlist, abs, trans, difference, entry; returnlist:=[]; trans:=List(center-point,Int); difference:=center-(trans+point); for entry in [1..Size(difference)] do abs:=AbsoluteValue(difference[entry]); if abs=1/2 then difference[entry]:=[0,SignRat(difference[entry])]; elif abs>1/2 then difference[entry]:=[SignRat(difference[entry])]; else difference[entry]:=[0]; fi; od; return trans+Cartesian(difference); end); hapcryst-0.2.0/lib/geometry.gd0000644000175100017510000000246015160525022015671 0ustar runnerrunner############################################################################# ## #W geometry.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## DeclareOperation("BisectorInequalityFromPointPair", [IsVector,IsVector,IsMatrix]); DeclareOperation("BisectorInequalityFromPointPair", [IsVector,IsVector]); DeclareOperation("WhichSideOfHyperplane", [IsVector,IsVector]); DeclareOperation("WhichSideOfHyperplaneNC", [IsVector,IsVector]); DeclareOperation("RelativePositionPointAndPolygon", [IsVector,IsPolymakeObject]); hapcryst-0.2.0/lib/misc.gi0000644000175100017510000000672615160525022015007 0ustar runnerrunner############################################################################# ## #W misc.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## # there seems to be not method for rationals, even though SignInt # did work in all of the cases I tried. InstallMethod(SignRat, "for rationals",[IsRat], function(rat) if rat>0 then return 1; elif rat<0 then return -1; elif rat=0 then return 0; else Error("cannot calculate sign of rational"); fi; #return SignInt(rat*DenominatorRat(rat)); end); ############################## InstallMethod(IsSquareMat,"for matrices",[IsMatrix], function(mat) return IsRectangularTable(mat) and NrRows(mat) = NrCols(mat); end); ############################## InstallMethod(DimensionSquareMat,"for matrices",[IsMatrix], function(mat) if not IsSquareMat(mat) then return fail; fi; return NrRows(mat); end); ############################## # # Return the linear part of an affine matrix. This is sometimes called # "rotational part" for crystallographic groups. # InstallMethod(LinearPartOfAffineMatOnRight,"for affine matrices on right", [IsMatrix], function(mat) local dim; if not IsAffineMatrixOnRight(mat) then Error("matrix must be an affine matrix acting from the right"); fi; dim:=DimensionSquareMat(mat); return mat{[1..dim-1]}{[1..dim-1]}; end); ############################## # # Calculate what a basis change of $n$ dimensional space does to an affine # transformation represented by an affine $(n+1)\times(n+1)$ matrix. # InstallMethod(BasisChangeAffineMatOnRight,"for affine matrices on right", [IsMatrix,IsMatrix], function(transform,mat) local dim, linpart, transpart, transformed; dim:=DimensionSquareMat(mat); if not dim>1 and IsAffineMatrixOnRight(mat) then Error("This matrix is not affine acting on right"); fi; linpart:=LinearPartOfAffineMatOnRight(mat); transpart:=mat[dim]{[1..dim-1]}; transformed:=IdentityMat(dim); transformed{[1..dim-1]}{[1..dim-1]}:=linpart^transform; transformed[dim]{[1..dim-1]}:=transpart*transform; return transformed; end); ############################## # # Return an affine matrix on right which represents the translation # by # InstallMethod(TranslationOnRightFromVector, [IsVector], function(vector) local dim, translation; dim:=Size(vector)+1; translation:=IdentityMat(dim); translation[dim]{[1..dim-1]}:=ShallowCopy(vector); return translation; end); ############################## # # InstallMethod(VectorModOne, [IsVector], function(vector) return List(vector,FractionModOne); end); hapcryst-0.2.0/lib/datatypes/0000755000175100017510000000000015160525022015516 5ustar runnerrunnerhapcryst-0.2.0/lib/datatypes/resolutionAccess_GroupRing.gi0000644000175100017510000005573515160525022023377 0ustar runnerrunner############################################################################# ## #W resolutionAccess_GroupRing.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## ## This file implements a representation for HapResolutions of large groups ## ## Elemements of the modules of this resolution are represented by ## integer-group element pairs. ## ## R!.elt must be present, but is not used for internal computations. ## It is used for conversion to and from the standard representation. ## ## HapLargeGroupResolution:=NewType(HapResolutionFamily,IsHapLargeGroupResolutionRep); ############################################################################# ## #O Dimension() ## ## overload the Hap function using !.diension2 ## InstallOtherMethod(Dimension, [IsHapLargeGroupResolutionRep], function(resolution) return function(k) return resolution!.dimension2(resolution,k);end; end); ############################################################################# ## #O Dimension(,) ## ## returns the dimension of the th module in . ## InstallOtherMethod(Dimension, [IsHapLargeGroupResolutionRep,IsInt], function(resolution,term) return resolution!.dimension2(resolution,term); end); ############################################################################# ## #O MultiplyGroupEltsNC(,,) #O MultiplyGroupEltsNC_LargeGroupRep(,,) ## ## catch, convert, delegate, convert ## InstallMethod(MultiplyGroupEltsNC,"for HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsPosInt,IsPosInt], function(resolution,x,y) local xgroup, ygroup, product; xgroup:=GroupElementFromPosition(resolution,x); ygroup:=GroupElementFromPosition(resolution,y); product:=MultiplyGroupEltsNC_LargeGroupRep(resolution,xgroup,ygroup); return PositionInGroupOfResolutionNC(resolution,product); end); InstallMethod(MultiplyGroupEltsNC_LargeGroupRep,"for HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsObject,IsObject], function(resolution,x,y) return x*y; end); ############################################################################# ## #O MultiplyGroupElts_LargeGroupRep(,,) ## ## interenal method for this representation. ## InstallMethod(MultiplyGroupElts_LargeGroupRep,"for HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsObject,IsObject], function(resolution,x,y) if not IsSubset(GroupOfResolution(resolution),[x,y]) then Error(" and must belong to 's group"); else return MultiplyGroupEltsNC_LargeGroupRep(resolution,x,y); fi; end); ############################################################################# ## #O MultiplyGroupElts(,,) ## ## interenal method for this representation. ## InstallMethod(MultiplyGroupElts,"for HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsObject,IsObject], function(resolution,x,y) if IsSubset(GroupOfResolution(resolution),[x,y]) then return MultiplyGroupEltsNC_LargeGroupRep(resolution,x,y); elif ForAll([x,y],i->IsValidGroupInt(resolution,i)) then return MultiplyGroupEltsNC(resolution,x,y); else TryNextMethod(); fi; end); ############################################################################# ## ## things which are used for the group ring things: ## InstallMethod(GroupRingOfResolution, [IsHapLargeGroupResolutionRep], function(resolution) return resolution!.groupring; end); ############################################################################# ## ## No "!"s allowed beyond this point ## ############################################################################# ############################################################################# ## #O StrongtestValidRepresentationForLetter(resolution,term,letter) ## ## returns the strongest representation in which is a valid letter ## for ## InstallMethod(StrongestValidRepresentationForLetter, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term, letter) if IsFreeZGLetter_LargeGroupRep(resolution,term,letter) then return IsHapLargeGroupResolutionRep; else TryNextMethod(); fi; end); ############################################################################# ## #O StrongtestValidRepresentationForWord(resolution,term,word) ## ## returns the strongest representation in which is a valid letter ## for ## InstallMethod(StrongestValidRepresentationForWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term, word) if IsFreeZGWord_LargeGroupRep(resolution,term,word) then return IsHapLargeGroupResolutionRep; else TryNextMethod(); fi; end); ############################################################################# ## #O ConvertStandardLetterToLargeGroupRepNC(,,) #O ConvertStandardLetterToLargeGroupRep(,,) ## InstallMethod(ConvertStandardLetter, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) if not IsFreeZGLetter(resolution,term,letter) then Error(" is not a valid letter"); fi; return ConvertStandardLetterNC(resolution,term,letter); end); InstallMethod(ConvertStandardLetterNC, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) local position, zero, family, zeroCoeff, dim, vector, i; position:=AbsInt(letter[1]); zero:=Zero(GroupRingOfResolution(resolution)); family:=FamilyObj(zero); zeroCoeff:=ZeroCoefficient(zero); dim:=Dimension(resolution,term); vector:=[]; for i in [dim,dim-1..1] do if i=position then vector[i]:=ElementOfMagmaRing(family, zeroCoeff, [SignInt(letter[1])], [GroupElementFromPosition(resolution,letter[2])] ); else vector[i]:=zero; fi; od; return vector; end); ############################################################################# ## #O ConvertStandardWordNC(,,) #O ConvertStandardWord(,,) ## InstallMethod(ConvertStandardWord, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,term,word) if not IsFreeZGWord(resolution,term,word) then Error(" is not a valid word"); fi; return ConvertStandardWordNC(resolution,term,word); end); ### This method needs improvement: InstallMethod(ConvertStandardWordNC, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,term,word) return Sum(List(word,letter->ConvertStandardLetterNC(resolution,term,letter))); end); ############################################################################# ## #O ConvertLetterToStandardRepNC #O ConvertLetterToStandardRep ## InstallMethod(ConvertLetterToStandardRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) if not IsFreeZGLetter_LargeGroupRep(resolution,term,letter) then Error(" is not a valid letter in large group representation."); fi; return ConvertLetterToStandardRepNC(resolution,term,letter); end); InstallMethod(ConvertLetterToStandardRepNC, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) local zero, pos, coeffsAndGroupElts; zero:=Zero(GroupRingOfResolution(resolution)); pos:=Position(letter,i->i<>zero); coeffsAndGroupElts:=CoefficientsAndMagmaElements(letter[pos]); return [pos*SignInt(coeffsAndGroupElts[2]),PositionInGroupOfResolution(resolution,coeffsAndGroupElts[1])]; end); ############################################################################# ## #O ConvertWordToStandardRepNC #O ConvertWordToStandardRep ## InstallMethod(ConvertWordToStandardRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,word) if not IsFreeZGWord_LargeGroupRep(resolution,term,word) then Error(" is not a valid letter in large group representation."); fi; return ConvertWordToStandardRepNC(resolution,term,word); end); InstallMethod(ConvertWordToStandardRepNC, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,word) local zero, stdword, pos, coeffsAndGroupElts, g, sign, mult; zero:=Zero(GroupRingOfResolution(resolution)); stdword:=[]; for pos in [1..Size(word)] do if word[pos]<>zero then coeffsAndGroupElts:=CoefficientsAndMagmaElements(word[pos]); for g in 2*[0..Size(coeffsAndGroupElts)/2-1]+1 do sign:=SignInt(coeffsAndGroupElts[g+1]); mult:=AbsInt(coeffsAndGroupElts[g]); Add(stdword,[sign*pos,PositionInGroupOfResolutionNC(resolution,coeffsAndGroupElts[g])]); od; fi; od; return stdword; end); ############################################################################# ## ## In this representation, it is easy to check if the letter can be ## an element of a certain module, if this check is passed. ## As we need this several times, it gets a special function: ## InstallMethod(IsFreeZGLetterNoTermCheck_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsDenseList], function(resolution,letter) local checkonly0, zero, i, coeffsAndGroupElts; checkonly0:=false; zero:=Zero(GroupRingOfResolution(resolution)); for i in letter do if not i in GroupRingOfResolution(resolution) then return false; elif checkonly0 then if i<>zero then return false; fi; elif i<>zero then coeffsAndGroupElts:=CoefficientsAndMagmaElements(i); if Size(coeffsAndGroupElts)>2 then return false; elif AbsInt(coeffsAndGroupElts[2])<>1 then return false; elif not coeffsAndGroupElts[1] in GroupOfResolution(resolution) then return false; else checkonly0:=true; fi; fi; od; return checkonly0; end); ############################################################################# ## #O IsFreeZGLetter_LargeGroupRep(,,) ## ## check if is a letter of the th module of . ## A letter is a word of length 1. ## ## InstallMethod(IsFreeZGLetter_LargeGroupRep,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) if Dimension(resolution,term)<>Size(letter) then return false; else return IsFreeZGLetterNoTermCheck_LargeGroupRep(resolution,letter); fi; end); ############################################################################# ## ## In this representation, it is easy to check if the word can be ## an element of a certain module, if this check is passed. ## As we need this several times, it gets a special function: ## InstallMethod(IsFreeZGWordNoTermCheck_LargeGroupRep, "For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsDenseList], function(resolution,word) local group, groupring, zero, i, coeffsAndGroupElts, j; group:=GroupOfResolution(resolution); groupring:=GroupRingOfResolution(resolution); zero:=Zero(groupring); for i in word do if not i in groupring then return false; else coeffsAndGroupElts:=CoefficientsAndMagmaElements(i); if coeffsAndGroupElts<>[] then for j in [0..Size(coeffsAndGroupElts)/2-1] do if not coeffsAndGroupElts[2*j+1] in group then return false; fi; od; fi; fi; od; return true; end); ############################################################################# ## #O IsFreeZGWord_LargeGroupRep(,,) ## ## Check if is an element of the th module in ## ## InstallMethod(IsFreeZGWord_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,word) if Size(word)<>Dimension(resolution,term) then return false; else return IsFreeZGWordNoTermCheck_LargeGroupRep(resolution,word); fi; end); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep(,,) ## ## given a pair of positive integers which represent a generator- ## group element pair, this returns the letter multiplied with the group ## element . ## ## InstallMethod(MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject], function(resolution,letter,g) local zero, pos, returnvector; zero:=Zero(GroupRingOfResolution(resolution)); pos:=PositionProperty(letter,i->i<>zero); returnvector:=ShallowCopy(letter); returnvector[pos]:=returnvector[pos]*g; return returnvector; end); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupElt_LargeGroupRep(,,) #O MultiplyFreeZGLetterWithGroupElt(,,) ## ## Check input for sanity and delegate to NC version ## InstallMethod(MultiplyFreeZGLetterWithGroupElt_LargeGroupRep, "For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject], function(resolution,letter,g) if not IsFreeZGLetterNoTermCheck_LargeGroupRep(resolution,letter) then Error(" or of wrong form"); fi; return MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep(resolution,letter,g); end); ############################################################################# ## InstallMethod(MultiplyFreeZGLetterWithGroupElt, "For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject], function(resolution,letter,g) if IsFreeZGLetterNoTermCheck_LargeGroupRep(resolution,letter) then return MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep(resolution,letter,g); else TryNextMethod(); fi; end); ############################################################################# ## #O MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep(,,) ## ## multiplies the word with the group element . ## No checks are performed. ## InstallMethod(MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject], function(resolution,word,g) return List(word,i->i*g); end); ############################################################################# ## #O MultiplyFreeZGWordWithGroupElt_LargeGroupRep(,,) #O MultiplyFreeZGWordWithGroupElt(,,) ## ## Check input and delegate to NC version. ## InstallMethod(MultiplyFreeZGWordWithGroupElt_LargeGroupRep,"For HapResolution", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject], function(resolution,word,g) if not (g in GroupOfResolution(resolution) and IsFreeZGWordNoTermCheck_LargeGroupRep(resolution,word) ) then Error("group element or word do not belong to resolution"); else return MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep(resolution,word,g); fi; end); ############################################################################# ## ## BoundaryOfGererator_LargeGroupRep ## InstallMethod(BoundaryOfGenerator_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsPosInt], function(resolution,term,gen) if not gen<=Dimension(resolution,term) then Error("so such generator"); else return BoundaryOfGeneratorNC_LargeGroupRep(resolution,term,gen); fi; end); ############################################################################# ## InstallMethod(BoundaryOfGeneratorNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsPosInt], function(resolution,term,gen) return resolution!.boundary2(resolution,term,gen); end); ############################################################################# ## #O BoundaryOfFreeZGLetterNC(,,) #O BoundaryOfFreeZGLetterNC_LargeGroupRep(,,) ## ## calculates the boundary of a cell in the th module. ## ## catch, convert, delegate, convert ## #InstallMethod(BoundaryOfFreeZGLetterNC,"For HapResolutions of large groups", # [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], # function(resolution,term,cell) # local cell_LargeGroupRep, boundary; # cell_LargeGroupRep:=[cell[1],GroupElementFromPosition(resolution,cell[2])]; # boundary:=BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,term,cell_LargeGroupRep); # Apply(boundary,i->[i[1], # PositionInGroupOfResolutionNC(resolution,i[2])]); # return boundary; #end); ############################################################################# ## InstallMethod(BoundaryOfFreeZGLetterNC_LargeGroupRep, "For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,cell) local zero, pos, boundary; zero:=Zero(GroupRingOfResolution(resolution)); pos:=PositionProperty(cell,i->i<>zero); boundary:=resolution!.boundary2(resolution,term,pos); return boundary*cell[pos]; end); ############################################################################# ## #O BoundaryOfFreeZGLetter_LargeGroupRep(,,) #O BoundaryOfFreeZGLetter(,,) ## ## checks input and delegates to NC version ## InstallMethod(BoundaryOfFreeZGLetter_LargeGroupRep,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) if not IsFreeZGLetter_LargeGroupRep(resolution,term,letter) then Error(" is not a proper letter"); fi; return BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,term,letter); end); ############################################################################# ## InstallMethod(BoundaryOfFreeZGLetter, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) local letter_large; if IsFreeZGLetter_LargeGroupRep(resolution,term,letter) then return BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,term,letter); elif IsFreeZGLetter(resolution,term,letter) then letter_large:=ConvertStandardLetterNC(resolution,term,letter); return ConvertWordToStandardRepNC(resolution,term,BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,term,letter_large)); else TryNextMethod(); fi; end); ############################################################################# ## #O BoundaryOfFreeZGWordNC_LargeGroupRep(,,) ## ## calculate the boundary of the element of the th module of the ## resolution . ## No checks done. ## InstallMethod(BoundaryOfFreeZGWordNC_LargeGroupRep,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,word) local zero, one, zerovec, returnword, dim, getBoundaryFor, boundary; zero:=Zero(GroupRingOfResolution(resolution)); one:=One(GroupRingOfResolution(resolution)); zerovec:=List([1..Size(word)],i->zero); returnword:=List([1..Dimension(resolution,term-1)],i->zero); for dim in [1..Size(word)] do if word[dim]<>zero then getBoundaryFor:=ShallowCopy(zerovec); getBoundaryFor[dim]:=one; boundary:=BoundaryOfFreeZGLetter_LargeGroupRep(resolution,term,getBoundaryFor)*word[dim]; returnword:=returnword+boundary; fi; od; return returnword; end); ############################################################################# ## #O BoundaryOfFreeZGWord_LargeGroupRep(,,) #O BoundaryOfFreeZGWord(,,) ## ## Check input and delegate to NC version. ## InstallMethod(BoundaryOfFreeZGWord_LargeGroupRep,"For HapResolution", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,word) if not IsFreeZGWord_LargeGroupRep(resolution,term,word) then Error(" is not an element of the th module"); fi; return BoundaryOfFreeZGWordNC_LargeGroupRep(resolution,term,word); end); ############################################################################# ## InstallMethod(BoundaryOfFreeZGWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) local word_large; if IsFreeZGWord_LargeGroupRep(resolution,term,letter) then return ConvertWordToStandardRepNC(resolution,term,BoundaryOfFreeZGWordNC_LargeGroupRep(resolution,term,letter) ); elif IsFreeZGLetter(resolution,term,letter) then word_large:=ConvertStandardWordNC(resolution,term,letter); return ConvertWordToStandardRepNC(resolution,term,BoundaryOfFreeZGWordNC_LargeGroupRep(resolution,term,word_large)); else TryNextMethod(); fi; end); ############################################################################# ## InstallMethod(GeneratorsOfModuleOfResolution_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt], function(resolution,term) local dim, zero, one, vector, generators, i, generator; dim:=Dimension(resolution,term); zero:=Zero(GroupRingOfResolution(resolution)); one:=One(GroupRingOfResolution(resolution)); vector:=List([1..dim],i->zero); generators:=[]; for i in [1..dim] do generator:=ShallowCopy(vector); generator[i]:=one; Add(generators,generator); od; return generators; end); hapcryst-0.2.0/lib/datatypes/contractingHomotopy_GroupRing.gd0000644000175100017510000000221515160525022024100 0ustar runnerrunner############################################################################# ## #W contractingHomotopy_GroupRing.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## DeclareOperation("MaximalSubspaceOfHomotopy_LargeGroupRep", [IsPartialContractingHomotopy,IsInt]); DeclareOperation("ImageOfContractingHomotopy_LargeGroupRep", [IsPartialContractingHomotopy,IsInt,IsDenseList]); hapcryst-0.2.0/lib/datatypes/resolutionAccess_generic.gi0000644000175100017510000003161415160525022023065 0ustar runnerrunner############################################################################# ## #W resolutionAccess_generic.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## ## README: ## ## This file contains the basic methods for accessing resolutions in Hap ## (fulfilling true=HapResolution(R) ). ## ## Every representation of a HapResolution that differs in the way ## module elements are written, must have special methods for treating them. ## This should be done in a catch-convert-delegate-convert way: ## ## First implement a method having the same name as one of the below ## but applying to resolutions in the special representation (replacing the ## "[IsHapResolution" bit with "[IsMyNewHapResolutionRep") ## This method should then call a function like _myRep doing all the ## calculations in the new representation (probably calling more of the ## _myRep functions). ## The output of _myRep should be converted into HapResolutionRep ## notation and returned. ## ## Even though it might be tempting not to, please obay the following rule: ## ## THERE MUST NOT BE A FUNCTION WHICH RETURNS DIFFERENT TYPES OF OUTPUT ## DEPENDING ON THE INPUT. ## ############################################################################# ## ## First, some access functions for resolutions ## ## - The position of a group element in 's enumeration ## - The th group element in 's enumeration ## - Check if the th element of the group of is known ## ## ############################################################################# ############################################################################# ## #O PositionInGroupOfResolutionNC(,) ## ## find the position in 's partial list of group elements ## . If is not contained in , it is ## added and the length of is returned. ## InstallMethod(PositionInGroupOfResolutionNC, "For HapResolutions", [IsHapResolution,IsObject], function(resolution,g) local pos; pos:=Position(resolution!.elts,g); if pos=fail then Add(resolution!.elts,g); pos:=Size(resolution!.elts); fi; return pos; end); ############################################################################# ## #O PositionInGroupOfResolution(,) ## ## find the position in 's partial list of group elements ## . ## This checkes Membership in 's group and then delegates ## to PositionInGroupOfResolutionNC ## InstallMethod(PositionInGroupOfResolution, "For HapResolutions", [IsHapResolution,IsObject], function(resolution,g) local pos; if not g in GroupOfResolution(resolution) then return fail; fi; return PositionInGroupOfResolutionNC(resolution,g); end); ############################################################################# ## #O IsValidGroupInt(,) ## ## test if there are elements of the group of known to the ## (partial) elements list ## InstallMethod(IsValidGroupInt,"for HapResolutions", [IsHapResolution,IsPosInt], function(resolution,n) return Size(resolution!.elts)>=n; end); ############################################################################# ## #O GroupElementFromPosition(,) ## ## returns the th element of 's (partial) list of group ## elements. ## InstallMethod(GroupElementFromPosition,"for HapResolutions", [IsHapResolution,IsPosInt], function(resolution,n) return resolution!.elts[n]; end); ############################################################################# ## #O MultiplyGroupEltsNC(,,) ## ## InstallMethod(MultiplyGroupEltsNC,"for HapResolutions", [IsHapResolution,IsPosInt,IsPosInt], function(resolution,x,y) local xgroup, ygroup; xgroup:=GroupElementFromPosition(resolution,x); ygroup:=GroupElementFromPosition(resolution,y); return PositionInGroupOfResolutionNC(resolution,xgroup*ygroup); end); ############################################################################# ## #O MultiplyGroupElts(,,) ## ## InstallMethod(MultiplyGroupElts,"for HapResolutions", [IsHapResolution,IsPosInt,IsPosInt], function(resolution,x,y) if not (IsValidGroupInt(resolution,x) and IsValidGroupInt(resolution,y) ) then Error(" and must represent elements of 's group"); else return MultiplyGroupEltsNC(resolution,x,y); fi; end); ############################################################################# ## ## This was it. From here on, ther will be no "!"s. ## ## Now, some functions for manipulating elements of the free modules ## of a resolution ## ## - Check if something really is a -letter ## - Check if something really is a an element of the th module ## - Multiply a letter with a group element ## - Multiply a module element (word) with a group element ## ## note that group elements are represented by their index in the enumeration ## of the group. ## ## ############################################################################# ############################################################################# ## #O StrongtestValidRepresentationForLetter(resolution,term,letter) ## ## returns the strongest representation in which is a valid letter ## for ## InstallMethod(StrongestValidRepresentationForLetter, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,term, letter) if IsFreeZGLetter(resolution,term,letter) then return IsHapResolutionRep; else TryNextMethod(); fi; end); ############################################################################# ## #O StrongtestValidRepresentationForWord(resolution,term,word) ## ## returns the strongest representation in which is a valid letter ## for ## InstallMethod(StrongestValidRepresentationForWord, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,term, word) if IsFreeZGWord(resolution,term,word) then return IsHapResolutionRep; else TryNextMethod(); fi; end); ############################################################################# ## #O IsFreeZGLetter(,,) ## ## check if is a letter of the th module of . ## A letter is a word of length 1. ## InstallMethod(IsFreeZGLetter,"For HapResolutions", [IsHapResolution,IsInt,IsDenseList], function(resolution,term,letter) if not ( Size(letter)=2 and ForAll(letter,IsInt) and AbsInt(letter[1])<=Dimension(resolution)(term) and IsValidGroupInt(resolution,letter[2]) ) then return false; else return true; fi; end); ############################################################################# ## #O IsFreeZGWord(,,) ## ## Check if is an element of the th module in ## InstallMethod(IsFreeZGWord,"For HapResolutions", [IsHapResolution,IsInt,IsDenseList], function(resolution,term,word) if not ForAll(word,IsDenseList) then return false; else return IsDenseList(word) and ForAll(word,c->IsFreeZGLetter(resolution,term,c)); fi; end); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupEltNC(,,) ## ## given a pair of positive integers which represent a generator- ## group element pair, this returns the letter multiplied with the group ## element . ## InstallMethod(MultiplyFreeZGLetterWithGroupEltNC,"For HapResolution", [IsHapResolution,IsDenseList,IsPosInt], function(resolution,letter,g) local newgroupel; newgroupel:=MultiplyGroupEltsNC(resolution,letter[2],g); return [letter[1],newgroupel]; end); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupElt(,,) ## ## Check input for sanity and delegate to NC version ## InstallMethod(MultiplyFreeZGLetterWithGroupElt,"For HapResolution", [IsHapResolution,IsDenseList,IsPosInt], function(resolution,letter,g) if not (IsValidGroupInt(resolution,letter[2]) and IsValidGroupInt(resolution,g) ) then Error("invalid group element indices"); fi; if not IsInt(letter[1]) then Error("first entry in letter must be an integer"); fi; return MultiplyFreeZGLetterWithGroupEltNC(resolution,letter,g); end); ############################################################################# ## #O MultiplyFreeZGWordWithGroupEltNC(,,) ## ## multiplies the word with the group element . ## No checks are performed. ## InstallMethod(MultiplyFreeZGWordWithGroupEltNC,"For HapResolution", [IsHapResolution,IsDenseList,IsPosInt], function(resolution,word,g) return List(word,letter->MultiplyFreeZGLetterWithGroupEltNC(resolution,letter,g)); end); ############################################################################# ## #O MultiplyFreeZGWordWithGroupElt(,,) ## ## Check input and delegate to NC version. ## InstallMethod(MultiplyFreeZGWordWithGroupElt,"For HapResolution", [IsHapResolution,IsDenseList,IsPosInt], function(resolution,word,g) if not IsFreeZGWord(resolution,word) then Error(" must be a valid ZG word"); fi; if not IsValidGroupInt(resolution,g) then Error(" is not a valid group element index"); fi; return MultiplyFreeZGWordWithGroupEltNC(resolution,word,g); end); ############################################################################# ## #O BoundaryOfFreeZGLetterNC(,,) ## ## calculates the boundary of a letter in the th module. ## InstallMethod(BoundaryOfFreeZGLetterNC,"For HapResolution", [IsHapResolution,IsInt,IsDenseList], function(resolution,term,letter) local sign, boundary; sign:=SignInt(letter[1]); boundary:=BoundaryMap(resolution)(term,AbsInt(letter[1])); boundary:=MultiplyFreeZGWordWithGroupEltNC(resolution,boundary,letter[2]); if sign=-1 then return NegateWord(boundary); else return boundary; fi; end); ############################################################################# ## #O BoundaryOfFreeZGLetter(,,) ## ## checks input and delegates to NC version ## InstallMethod(BoundaryOfFreeZGLetter,"For HapResolution", [IsHapResolution,IsInt,IsDenseList], function(resolution,term,letter) if not IsFreeZGLetter(resolution,term,letter) then Error(" is not a proper letter"); fi; return BoundaryOfFreeZGLetterNC(resolution,term,letter); end); ############################################################################# ## #O BoundaryOfFreeZGWordNC(,,) ## ## calculate the boundary of the element of the th module of the ## resolution . ## No checks done. ## InstallMethod(BoundaryOfFreeZGWordNC,"For HapResolution", [IsHapResolution,IsInt,IsDenseList], function(resolution,term,word) local boundary, letter, letterbound; boundary:=[]; for letter in word do letterbound:=BoundaryOfFreeZGLetterNC(resolution,term,letter); boundary:=AddFreeWords(boundary,letterbound); od; return boundary; end); ############################################################################# ## #O BoundaryOfFreeZGWord(,,) ## ## Check input and delegate to NC version. ## InstallMethod(BoundaryOfFreeZGWord,"For HapResolution", [IsHapResolution,IsInt,IsDenseList], function(resolution,term,word) if not IsFreeZGWord(resolution,term,word) then Error(" is not an element of the th module"); fi; return BoundaryOfFreeZGWordNC(resolution,term,word); end); hapcryst-0.2.0/lib/datatypes/resolutionAccess_GroupRing.gd0000644000175100017510000002434615160525022023364 0ustar runnerrunner############################################################################# ## #W resolutionAccess_GroupRing.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## ## This file defines a representation for HapResolutions of lrge groups. ## ## Elements of the modules in these resolutions are integer- group element ## pairs. ## ## DeclareRepresentation("IsHapLargeGroupResolutionRep", IsHapResolutionRep, ["dimension2", "boundary2"] ); ############################################################################# ## #O Dimension(,) ## ## returns the dimension of the th module in . ## DeclareOperation("Dimension",[IsHapLargeGroupResolutionRep,IsInt]); ############################################################################# ## #O GroupRingOfResolution() ## ## DeclareOperation("GroupRingOfResolution",[IsHapLargeGroupResolutionRep]); ############################################################################# ## #O BoundaryMap() ## ## overload the Hap function using !.boundary2 ## #DeclareOperation("BoundaryMap",[IsHapLargeGroupResolutionRep]); ############################################################################# ## #O MultiplyGroupEltsNC(,,) #O MultiplyGroupEltsNC_LargeGroupRep(,,) ## ## catch, convert, delegate, convert ## DeclareOperation("MultiplyGroupEltsNC", [IsHapLargeGroupResolutionRep,IsPosInt,IsPosInt]); DeclareOperation("MultiplyGroupEltsNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsObject,IsObject]); ############################################################################# ## #O MultiplyGroupElts_LargeGroupRep(,,) ## ## internal method for this representation. ## DeclareOperation("MultiplyGroupElts_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsObject,IsObject]); ############################################################################# ## #O MultiplyGroupElts(,,) ## ## for x,y in other representations ## DeclareOperation("MultiplyGroupElts", [IsHapLargeGroupResolutionRep,IsObject,IsObject]); ############################################################################# ## #O ConvertStandardLetterNC(,,) #O ConvertStandardLetter(,,) ## DeclareOperation("ConvertStandardLetterNC", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("ConvertStandardLetter", [IsHapResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O ConvertStandardWordNC(,,) #O ConvertStandardWord(,,) ## DeclareOperation("ConvertStandardWordNC", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("ConvertStandardWord", [IsHapResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O ConvertLetterToStandardRepNC #O ConvertLetterToStandardRep ## DeclareOperation("ConvertLetterToStandardRepNC", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("ConvertLetterToStandardRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O ConvertLargeGroupRepWordToStandardRepNC #O ConvertLargeGroupRepWordToStandardRep ## DeclareOperation("ConvertWordToStandardRepNC", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("ConvertWordToStandardRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O IsFreeZGLetterNoTermCheck_LargeGroupRep(resoltuion,letter) ## ## tests if . ## It is not checked whether the length of actually matches up with ## some dimension of a module in ## DeclareOperation("IsFreeZGLetterNoTermCheck_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList]); ############################################################################# ## #O IsFreeZGLetter_LargeGroupRep(,,) ## ## check if is a letter of the th module of . ## A letter is a word of length 1. ## ## DeclareOperation("IsFreeZGLetter_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O IsFreeZGWordNoTermCheck_LargeGroupRep(resoltuion,word) ## ## tests if can be a word of any module of . ## It is not checked whether the length of actually matches up with ## some dimension of a module in ## DeclareOperation("IsFreeZGWordNoTermCheck_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList]); ############################################################################# ## #O IsFreeZGWord_LargeGroupRep(,,) ## ## Check if is an element of the th module in ## ## DeclareOperation("IsFreeZGWord_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep(,,) ## ## given a pair of positive integers which represent a generator- ## group element pair, this returns the letter multiplied with the group ## element . ## ## DeclareOperation("MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupElt_LargeGroupRep(,,) #O MultiplyFreeZGLetterWithGroupElt(,,) ## ## Check input for sanity and delegate to NC version ## DeclareOperation("MultiplyFreeZGLetterWithGroupElt_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); DeclareOperation("MultiplyFreeZGLetterWithGroupElt", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); ############################################################################# ## #O MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep(,,) ## ## multiplies the word with the group element . ## No checks are performed. ## DeclareOperation("MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); DeclareOperation("MultiplyFreeZGWordWithGroupEltNC", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); ############################################################################# ## #O MultiplyFreeZGWordWithGroupElt_LargeGroupRep(,,) ## ## Check input and delegate to NC version. ## DeclareOperation("MultiplyFreeZGWordWithGroupElt_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); ############################################################################# ## ## DeclareOperation("BoundaryOfGenerator_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsPosInt]); DeclareOperation("BoundaryOfGeneratorNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsPosInt]); ############################################################################# ## #O BoundaryOfFreeZGLetterNC(,,) #O BoundaryOfFreeZGLetterNC_LargeGroupRep(,,) ## ## calculates the boundary of a letter in the th module. ## ## catch, convert, delegate, convert ## DeclareOperation("BoundaryOfFreeZGLetterNC", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("BoundaryOfFreeZGLetterNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("BoundaryOfFreeZGLetter", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O BoundaryOfFreeZGLetter_LargeGroupRep(,,) ## ## checks input and delegates to NC version ## DeclareOperation("BoundaryOfFreeZGLetter_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O BoundaryOfFreeZGWordNC_LargeGroupRep(,,) ## ## calculate the boundary of the element of the th module of the ## resolution . ## No checks done. ## DeclareOperation("BoundaryOfFreeZGWordNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O BoundaryOfFreeZGWord_LargeGroupRep(,,) #O BoundaryOfFreeZGWord(,,) ## ## Check input and delegate to NC version. ## DeclareOperation("BoundaryOfFreeZGWord_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("BoundaryOfFreeZGWord", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O GeneratorsOfModuleOfResolution_LargeGroupRep(resolution,term) ## ## returns generators of the th module of as a list ## of vectors of group ring elements. ## DeclareOperation("GeneratorsOfModuleOfResolution_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt]); hapcryst-0.2.0/lib/datatypes/resolutionAccess_LargeGroupRep.gd0000644000175100017510000002255615160525022024167 0ustar runnerrunner############################################################################# ## #W resolutionAccess_LargeGroupRep.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## ## This file defines a representation for HapResolutions of lrge groups. ## ## Elements of the modules in these resolutions are integer- group element ## pairs. ## ## DeclareRepresentation("IsHapLargeGroupResolutionRep", IsHapResolutionRep, ["dimension2", "boundary2"] ); HapLargeGroupResolution:=NewType(HapResolutionFamily,IsHapLargeGroupResolutionRep); ############################################################################# ## #O Dimension() ## ## overload the Hap function using !.diension2 ## #DeclareOperation("Dimension",[IsHapLargeGroupResolutionRep]); ############################################################################# ## #O BoundaryMap() ## ## overload the Hap function using !.boundary2 ## DeclareOperation("BoundaryMap",[IsHapLargeGroupResolutionRep]); ############################################################################# ## #O MultiplyGroupEltsNC(,,) #O MultiplyGroupEltsNC_LargeGroupRep(,,) ## ## catch, convert, delegate, convert ## DeclareOperation("MultiplyGroupEltsNC", [IsHapLargeGroupResolutionRep,IsPosInt,IsPosInt]); DeclareOperation("MultiplyGroupEltsNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsObject,IsObject]); ############################################################################# ## #O MultiplyGroupElts_LargeGroupRep(,,) ## ## internal method for this representation. ## DeclareOperation("MultiplyGroupElts_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsObject,IsObject]); ############################################################################# ## #O MultiplyGroupElts(,,) ## ## for x,y in other representations ## DeclareOperation("MultiplyGroupElts", [IsHapLargeGroupResolutionRep,IsObject,IsObject]); ############################################################################# ## #O StrongtestValidRepresentationForLetter(resolution,term,letter) ## ## returns the strongest representation in which is a valid letter ## for ## DeclareOperation("StrongestValidRepresentationForLetter", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O StrongtestValidRepresentationForWord(resolution,term,word) ## ## returns the strongest representation in which is a valid letter ## for ## DeclareOperation("StrongestValidRepresentationForWord", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O ConvertStandardLetterNC(,,) #O ConvertStandardLetter(,,) ## DeclareOperation("ConvertStandardLetterNC", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("ConvertStandardLetter", [IsHapResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O ConvertStandardWordNC(,,) #O ConvertStandardWord(,,) ## DeclareOperation("ConvertStandardWordNC", [IsHapResolutionRep,IsInt,IsDenseList]); DeclareOperation("ConvertStandardWord", [IsHapResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O ConvertLetterToStandardRepNC #O ConvertLetterToStandardRep ## DeclareOperation("ConvertLetterToStandardRepNC", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("ConvertLetterToStandardRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O ConvertLargeGroupRepWordToStandardRepNC #O ConvertLargeGroupRepWordToStandardRep ## DeclareOperation("ConvertWordToStandardRepNC", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("ConvertWordToStandardRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O IsFreeZGLetter_LargeGroupRep(,,) ## ## check if is a letter of the th module of . ## A letter is a word of length 1. ## ## DeclareOperation("IsFreeZGLetter_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O IsFreeZGWord_LargeGroupRep(,,) ## ## Check if is an element of the th module in ## ## DeclareOperation("IsFreeZGWord_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep(,,) ## ## given a pair of positive integers which represent a generator- ## group element pair, this returns the letter multiplied with the group ## element . ## ## DeclareOperation("MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupElt_LargeGroupRep(,,) #O MultiplyFreeZGLetterWithGroupElt(,,) ## ## Check input for sanity and delegate to NC version ## DeclareOperation("MultiplyFreeZGLetterWithGroupElt_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); DeclareOperation("MultiplyFreeZGLetterWithGroupElt", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); ############################################################################# ## #O MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep(,,) ## ## multiplies the word with the group element . ## No checks are performed. ## DeclareOperation("MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); DeclareOperation("MultiplyFreeZGWordWithGroupEltNC", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); ############################################################################# ## #O MultiplyFreeZGWordWithGroupElt_LargeGroupRep(,,) ## ## Check input and delegate to NC version. ## DeclareOperation("MultiplyFreeZGWordWithGroupElt_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); DeclareOperation("MultiplyFreeZGWordWithGroupElt", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject]); ############################################################################# ## #O BoundaryOfFreeZGLetterNC(,,) #O BoundaryOfFreeZGLetterNC_LargeGroupRep(,,) ## ## calculates the boundary of a letter in the th module. ## ## catch, convert, delegate, convert ## DeclareOperation("BoundaryOfFreeZGLetterNC", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("BoundaryOfFreeZGLetterNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O BoundaryOfFreeZGLetter_LargeGroupRep(,,) ## ## checks input and delegates to NC version ## DeclareOperation("BoundaryOfFreeZGLetter_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("BoundaryOfFreeZGLetter", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O BoundaryOfFreeZGWordNC_LargeGroupRep(,,) ## ## calculate the boundary of the element of the th module of the ## resolution . ## No checks done. ## DeclareOperation("BoundaryOfFreeZGWordNC_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O BoundaryOfFreeZGWord_LargeGroupRep(,,) #O BoundaryOfFreeZGWord(,,) ## ## Check input and delegate to NC version. ## DeclareOperation("BoundaryOfFreeZGWord_LargeGroupRep", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); DeclareOperation("BoundaryOfFreeZGWord", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList]); hapcryst-0.2.0/lib/datatypes/contractingHomotopy_GroupRing.gi0000644000175100017510000001150615160525022024110 0ustar runnerrunner############################################################################# ## #W contractingHomotopy_GroupRing.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## #O MaximalSubspaceOfHomotopy_LargeGroupRep() ## InstallMethod(MaximalSubspaceOfHomotopy_LargeGroupRep, [IsPartialContractingHomotopy,IsInt], function(homotopy,term) local resolution; resolution:=ResolutionOfContractingHomotopy(homotopy); if not IsHapLargeGroupResolutionRep(resolution) then Error("not implemented yet. Resolution not in large group rep"); fi; return homotopy!.knownPartOfHomotopy[term+1].space; end); ############################################################################# ## #O ImageOfContractinghomotopy_LargeGroupRep ## InstallMethod (ImageOfContractingHomotopy_LargeGroupRep, [IsPartialContractingHomotopy,IsInt,IsDenseList], function(homotopy,term,word) local resolution, wordCoeffs, grpWordUndir, i, coeffsgrpels, zero, zerocoeff, zerovec, upzerovec, family, embedding, returnword, g, image, letter, firstimage, upcell, sign, bound, boundi, pos, otherimages, j; resolution:=ResolutionOfContractingHomotopy(homotopy); if not IsFreeZGWord_LargeGroupRep(resolution,term,word) then Error("invalid "); fi; wordCoeffs:=List([1..Size(word)],i->[]); grpWordUndir:=List([1..Size(word)],i->[]); for i in [1..Size(word)] do coeffsgrpels:=CoefficientsAndMagmaElementsAsLists(word[i]); wordCoeffs[i]:=coeffsgrpels[1]; grpWordUndir[i]:=coeffsgrpels[2]; od; zero:=Zero(GroupRingOfResolution(resolution)); zerocoeff:=ZeroCoefficient(zero); zerovec:=ListWithIdenticalEntries(Size(word),zero); upzerovec:=ListWithIdenticalEntries(Dimension(resolution)(term+1),zero); family:=FamilyObj(zero); embedding:=Embedding(GroupOfResolution(resolution),GroupRingOfResolution(resolution)); returnword:=upzerovec; for i in [1..Size(word)] do for g in [1..Size(grpWordUndir[i])] do image:=PartialContractingHomotopyLookup(homotopy,term,i,grpWordUndir[i][g]); if image=fail then letter:=ShallowCopy(zerovec); letter[i]:=Image(embedding,grpWordUndir[i][g]); if not IsUndirectedSubWord_LargeGroupRep(resolution, MaximalSubspaceOfHomotopy_LargeGroupRep(homotopy,term), letter ) then Error("not implemented yet"); fi; else if image[2]<>[] then sign:=SignInt(image[2][1]); firstimage:=sign*Image(embedding,image[2][2]); upcell:=ShallowCopy(upzerovec); upcell[AbsInt(image[2][1])]:=firstimage; bound:=BoundaryOfFreeZGWordNC_LargeGroupRep(resolution,term+1,upcell); #### ## This assumes that there is one and only one +1 face ## assigned to every face. ## This will not work for any other homotopy! boundi:=CoefficientsAndMagmaElementsAsLists(bound[i]); pos:=Position(boundi[2],grpWordUndir[i][g]); Unbind(boundi[1][pos]); Unbind(boundi[2][pos]); bound[i]:=ElementOfMagmaRing(family,zerocoeff,Compacted(boundi[1]),Compacted(boundi[2])); otherimages:=ImageOfContractingHomotopy_LargeGroupRep(homotopy,term,bound); otherimages:=List(otherimages,x->wordCoeffs[i][g]*x); returnword:=returnword-otherimages; j:=AbsInt(image[2][1]); returnword[j]:=returnword[j]+wordCoeffs[i][g]*firstimage; fi; fi; od; od; return -returnword; ## all those minusses aren't nice. But I don't want to go chasing signs ## again... end);hapcryst-0.2.0/lib/datatypes/contractingHomotopy.gi0000644000175100017510000000775115160525022022123 0ustar runnerrunner############################################################################# ## #W contractingHomotopy.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## PartialContractingHomotopyFamily:=NewFamily("PartialContractingHomotopyFamily", IsPartialContractingHomotopy ); PartialContractingHomotopy:=NewType(PartialContractingHomotopyFamily, IsPartialContractingHomotopyRep ); ############################################################################# ## ## Printing homotopies: ## InstallMethod(ViewObj, "for PartialContractingHomotopy", [IsPartialContractingHomotopy], function(homotopy) Print(""); end); InstallMethod(PrintObj, "for PartialContractingHomotopy", [IsPartialContractingHomotopy], function(homotopy) Print(""); end); ############################################################################# ## ## Accessing private data: ## ############################################################################# ## #O ResolutionOfContractingHomotopy() ## InstallMethod(ResolutionOfContractingHomotopy, [IsPartialContractingHomotopy], function(homotopy) return homotopy!.resolution; end); ############################################################################# ## #O PartialContractingHomotopyLookup(,,,) ## ## lookup the value of the th generator times and ## return it. If it is unknown, return fail. ## InstallMethod(PartialContractingHomotopyLookup, [IsPartialContractingHomotopy,IsInt,IsPosInt,IsObject], function(homotopy,term,generator,groupel) local resolution; resolution:=ResolutionOfContractingHomotopy(homotopy); if term>=EvaluateProperty(resolution,"length") then Error("resolution too short"); elif not generator<=Dimension(resolution)(term) then Error("no such generator"); fi; return PartialContractingHomotopyLookupNC(homotopy,term,generator,groupel); end); ############################################################################# ## #O PartialContractingHomotopyLookupNC(,,,) ## ## lookup the value of the th generator times and ## return it. If it is unknown, return fail. ## Input not checked. ## InstallMethod(PartialContractingHomotopyLookupNC, [IsPartialContractingHomotopy,IsInt,IsPosInt,IsObject], function(homotopy,term,generator,groupel) local knownMap, space; knownMap:=homotopy!.knownPartOfHomotopy; if not (IsBound(knownMap[term+2]) and IsBound(knownMap[term+1])) then return fail; fi; space:=knownMap[term+1].space; knownMap:=knownMap[term+2].map; if not IsBound(knownMap[generator]) or knownMap[generator]=[] then return fail; else return First(knownMap[generator],x->x[1]=groupel); fi; end); ############################################################################# ## #E End ##hapcryst-0.2.0/lib/datatypes/resolutionAccess_SmallGroupRep.gi0000644000175100017510000000747315160525022024213 0ustar runnerrunner############################################################################# ## #W resolutionAccess_SmallGroupRep.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## ## This file implements a representation for HapResolutions of small groups. ## ## The additional feature of this representation is the multiplication ## via a multiplication table. ## Also, the list of group elements R!.elts is a set. So we can do binary ## search occasionally. ## ## Elements of the modules in these resolutions are still pairs of integers. ## ## ############################################################################# ## #O PositionInGroupOfResolutionNC(,) #O PositionInGroupOfResolution(,) ## ## find the position in 's partial list of group elements ## . If is not contained in , it is ## added and the length of is returned. ## ## The SmallGroupRep is consistent. So we just catch. ## InstallMethod(PositionInGroupOfResolutionNC, "For HapResolutions of small groups", [IsHapSmallGroupResolutionRep,IsObject], function(resolution,g) local pos; return PositionSet(resolution!.elts,g); end); InstallMethod(PositionInGroupOfResolution, "For HapResolutions of small groups", [IsHapSmallGroupResolutionRep,IsObject], function(resolution,g) local pos; if not g in GroupOfResolution(resolution) then Error(" is not in 's group"); fi; return PositionInGroupOfResolutionNC(resolution,g); end); ############################################################################# ## #O MultiplyGroupEltsNC(,,) ## ## catch the call and delegate to special method. No conversion needed. ## InstallMethod(MultiplyGroupEltsNC,"for HapResolutions of small groups", [IsHapSmallGroupResolutionRep,IsPosInt,IsPosInt], function(resolution,x,y) return resolution!.multtable[x][y]; end); ############################################################################# ############################################################################# ## ## NO "!"s allowed beyond this point ## ############################################################################# ############################################################################# ############################################################################# ## #O MultiplyFreeZGLetterWithGroupEltNC(,,) ## ## given a pair of positive integers which represent a generator- ## group element pair, this returns the letter multiplied with the group ## element . ## ## InstallMethod(MultiplyFreeZGLetterWithGroupEltNC,"For HapResolutions of small groups", [IsHapSmallGroupResolutionRep,IsDenseList,IsPosInt], function(resolution,letter,g) local newgroupel; newgroupel:=MultiplyGroupEltsNC(resolution,letter[2],g); return [letter[1],PositionInGroupOfResolution(resolution,newgroupel)]; end); hapcryst-0.2.0/lib/datatypes/contractingHomotopy.gd0000644000175100017510000000402415160525022022104 0ustar runnerrunner############################################################################# ## #W contractingHomotopy.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## ## "knownPartOfHomotopy" is a list of records with components ## .space : a contractible space ## .map : a list of lists of pairs such that ## the (k,i)^th entry contains pairs [g,[j,h]] where g,h are group elts ## and j refers to a generator in term k+1. ## read as: i^th generator in term k times g gets mapped to ## the j^th generator in term k+1 times h. ## DeclareCategory("IsPartialContractingHomotopy",IsObject); DeclareRepresentation("IsPartialContractingHomotopyRep", IsComponentObjectRep, ["resolution", "knownPartOfHomotopy" ] ); ############################################################################# DeclareOperation("ResolutionOfContractingHomotopy",[IsPartialContractingHomotopy]); DeclareOperation("PartialContractingHomotopyLookup", [IsPartialContractingHomotopy,IsInt,IsPosInt,IsObject]); DeclareOperation("PartialContractingHomotopyLookupNC", [IsPartialContractingHomotopy,IsInt,IsPosInt,IsObject]); hapcryst-0.2.0/lib/datatypes/resolutionAccess_LargeGroupRep.gi0000644000175100017510000004323415160525022024170 0ustar runnerrunner############################################################################# ## #W resolutionAccess_LargeGroupRep.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## ## This file implements a representation for HapResolutions of large groups ## ## Elemements of the modules of this resolution are represented by ## integer-group element pairs. ## ## R!.elt must be present, but is not used for internal computations. ## It is used for conversion to and from the standard representation. ## ## ############################################################################# ## #O Dimension() ## ## overload the Hap function using !.diension2 ## InstallOtherMethod(Dimension, [IsHapLargeGroupResolutionRep], function(resolution) return function(k) return resolution!.dimension2(resolution,k);end; end); ############################################################################# ## #O MultiplyGroupEltsNC(,,) #O MultiplyGroupEltsNC_LargeGroupRep(,,) ## ## catch, convert, delegate, convert ## InstallMethod(MultiplyGroupEltsNC,"for HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsPosInt,IsPosInt], function(resolution,x,y) local xgroup, ygroup, product; xgroup:=GroupElementFromPosition(resolution,x); ygroup:=GroupElementFromPosition(resolution,y); product:=MultiplyGroupEltsNC_LargeGroupRep(resolution,xgroup,ygroup); return PositionInGroupOfResolutionNC(resolution,product); end); InstallMethod(MultiplyGroupEltsNC_LargeGroupRep,"for HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsObject,IsObject], function(resolution,x,y) return x*y; end); ############################################################################# ## #O MultiplyGroupElts_LargeGroupRep(,,) ## ## interenal method for this representation. ## InstallMethod(MultiplyGroupElts_LargeGroupRep,"for HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsObject,IsObject], function(resolution,x,y) if not IsSubset(GroupOfResolution(resolution),[x,y]) then Error(" and must belong to 's group"); else return MultiplyGroupEltsNC_LargeGroupRep(resolution,x,y); fi; end); ############################################################################# ## #O MultiplyGroupElts(,,) ## ## interenal method for this representation. ## InstallMethod(MultiplyGroupElts,"for HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsObject,IsObject], function(resolution,x,y) if IsSubset(GroupOfResolution(resolution),[x,y]) then return MultiplyGroupEltsNC_LargeGroupRep(resolution,x,y); elif ForAll([x,y],i->IsValidGroupInt(resolution,i)) then return MultiplyGroupEltsNC(resolution,x,y); else TryNextMethod(); fi; end); ############################################################################# ## ## No "!"s allowed beyond this point ## ############################################################################# ############################################################################# ## #O StrongtestValidRepresentationForLetter(resolution,term,letter) ## ## returns the strongest representation in which is a valid letter ## for ## InstallMethod(StrongestValidRepresentationForLetter, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term, letter) if IsFreeZGLetter_LargeGroupRep(resolution,term,letter) then return IsHapLargeGroupResolutionRep; else TryNextMethod(); fi; end); ############################################################################# ## #O StrongtestValidRepresentationForWord(resolution,term,word) ## ## returns the strongest representation in which is a valid letter ## for ## InstallMethod(StrongestValidRepresentationForWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term, word) if IsFreeZGWord_LargeGroupRep(resolution,term,word) then return IsHapLargeGroupResolutionRep; else TryNextMethod(); fi; end); ############################################################################# ## #O ConvertStandardLetterToLargeGroupRepNC(,,) #O ConvertStandardLetterToLargeGroupRep(,,) ## InstallMethod(ConvertStandardLetter, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) if not IsFreeZGLetter(resolution,term,letter) then Error(" is not a valid letter"); fi; return ConvertStandardLetterNC(resolution,term,letter); end); InstallMethod(ConvertStandardLetterNC, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) return [letter[1],GroupElementFromPosition(resolution,letter[2])]; end); ############################################################################# ## #O ConvertStandardWordNC(,,) #O ConvertStandardWord(,,) ## InstallMethod(ConvertStandardWord, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,term,word) if not IsFreeZGWord(resolution,term,word) then Error(" is not a valid word"); fi; return ConvertStandardWordNC(resolution,term,word); end); InstallMethod(ConvertStandardWordNC, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,term,word) return List(word,letter->ConvertStandardLetterNC(resolution,term,letter)); end); ############################################################################# ## #O ConvertLetterToStandardRepNC #O ConvertLetterToStandardRep ## InstallMethod(ConvertLetterToStandardRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) if not IsFreeZGLetter_LargeGroupRep(resolution,term,letter) then Error(" is not a valid letter in large group representation."); fi; return ConvertLetterToStandardRepNC(resolution,term,letter); end); InstallMethod(ConvertLetterToStandardRepNC, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) return [letter[1],PositionInGroupOfResolution(resolution,letter[2])]; end); ############################################################################# ## #O ConvertWordToStandardRepNC #O ConvertWordToStandardRep ## InstallMethod(ConvertWordToStandardRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,word) if not IsFreeZGWord_LargeGroupRep(resolution,term,word) then Error(" is not a valid letter in large group representation."); fi; return ConvertWordToStandardRepNC(resolution,term,word); end); InstallMethod(ConvertWordToStandardRepNC, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,word) return List(word,letter->ConvertLetterToStandardRepNC(resolution,term,letter)); end); ############################################################################# ## #O IsFreeZGLetter_LargeGroupRep(,,) ## ## check if is a letter of the th module of . ## A letter is a word of length 1. ## ## InstallMethod(IsFreeZGLetter_LargeGroupRep,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) if not ( Size(letter)=2 and IsInt(letter[1]) and AbsInt(letter[1])<=Dimension(resolution)(term) and letter[2] in GroupOfResolution(resolution) ) then return false; else return true; fi; end); ############################################################################# ## #O IsFreeZGWord_LargeGroupRep(,,) ## ## Check if is an element of the th module in ## ## InstallMethod(IsFreeZGWord_LargeGroupRep,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,word) local firstEntries, secondEntries; if not ForAll(word,IsDenseList) then return false; fi; firstEntries:=List(word,i->AbsInt(i[1])); secondEntries:=Set(word,i->i[2]); if Maximum(firstEntries)<=Dimension(resolution)(term) and IsSubset(GroupOfResolution(resolution),secondEntries) then return true; else return false; fi; end); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep(,,) ## ## given a pair of positive integers which represent a generator- ## group element pair, this returns the letter multiplied with the group ## element . ## ## InstallMethod(MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject], function(resolution,letter,g) local newgroupel; return [letter[1],letter[2]*g]; end); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupElt_LargeGroupRep(,,) #O MultiplyFreeZGLetterWithGroupElt(,,) ## ## Check input for sanity and delegate to NC version ## InstallMethod(MultiplyFreeZGLetterWithGroupElt_LargeGroupRep,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject], function(resolution,letter,g) if not (IsSubset(GroupOfResolution(resolution),[g,letter[2]]) and IsInt(letter[1]) ) then Error(" or of wrong form"); fi; return MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep(resolution,letter,g); end); ############################################################################# ## InstallMethod(MultiplyFreeZGLetterWithGroupElt,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject], function(resolution,letter,g) if not (IsSubset(GroupOfResolution(resolution),[g,letter[2]]) and IsInt(letter[1]) ) then TryNextMethod(); fi; return MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep(resolution,letter,g); end); ############################################################################# ## #O MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep(,,) ## ## multiplies the word with the group element . ## No checks are performed. ## InstallMethod(MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject], function(resolution,word,g) return List(word,cell->MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep(resolution,cell,g)); end); ############################################################################# ## #O MultiplyFreeZGWordWithGroupElt_LargeGroupRep(,,) #O MultiplyFreeZGWordWithGroupElt(,,) ## ## Check input and delegate to NC version. ## InstallMethod(MultiplyFreeZGWordWithGroupElt_LargeGroupRep,"For HapResolution", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject], function(resolution,word,g) local group; group:=GroupOfResolution(resolution); if not (ForAll(word,i->IsInt(i[1]) and i[2] in group) and g in group ) then Error(" or are not valid"); fi; return MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep(resolution,word,g); end); ############################################################################# ## InstallMethod(MultiplyFreeZGWordWithGroupElt,"For HapResolution", [IsHapLargeGroupResolutionRep,IsDenseList,IsObject], function(resolution,word,g) local group; group:=GroupOfResolution(resolution); if not (ForAll(word,i->IsInt(i[1]) and i[2] in group) and g in group ) then TryNextMethod(); fi; return MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep(resolution,word,g); end); ############################################################################# ## #O BoundaryOfFreeZGLetterNC(,,) #O BoundaryOfFreeZGLetterNC_LargeGroupRep(,,) ## ## calculates the boundary of a cell in the th module. ## ## catch, convert, delegate, convert ## InstallMethod(BoundaryOfFreeZGLetterNC,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,cell) local cell_LargeGroupRep, boundary; cell_LargeGroupRep:=[cell[1],GroupElementFromPosition(resolution,cell[2])]; boundary:=BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,term,cell_LargeGroupRep); Apply(boundary,i->[i[1], PositionInGroupOfResolutionNC(resolution,i[2])]); return boundary; end); ############################################################################# ## InstallMethod(BoundaryOfFreeZGLetterNC_LargeGroupRep, "For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,cell) local sign, boundary; sign:=SignInt(cell[1]); boundary:=resolution!.boundary2(resolution,term,AbsInt(cell[1])); boundary:=MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep(resolution,boundary,cell[2]); if sign=-1 then return NegateWord(boundary); else return boundary; fi; end); ############################################################################# ## #O BoundaryOfFreeZGLetter_LargeGroupRep(,,) #O BoundaryOfFreeZGLetter(,,) ## ## checks input and delegates to NC version ## InstallMethod(BoundaryOfFreeZGLetter_LargeGroupRep,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) if not IsFreeZGLetter_LargeGroupRep(resolution,term,letter) then Error(" is not a proper letter"); fi; return BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,term,letter); end); ############################################################################# ## InstallMethod(BoundaryOfFreeZGLetter, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) local letter_large; if IsFreeZGLetter_LargeGroupRep(resolution,term,letter) then return BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,term,letter); elif IsFreeZGLetter(resolution,term,letter) then letter_large:=ConvertStandardLetterNC(resolution,term,letter); return ConvertWordToStandardRepNC(resolution,term,BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,term,letter_large)); else TryNextMethod(); fi; end); ############################################################################# ## #O BoundaryOfFreeZGWordNC_LargeGroupRep(,,) ## ## calculate the boundary of the element of the th module of the ## resolution . ## No checks done. ## InstallMethod(BoundaryOfFreeZGWordNC_LargeGroupRep,"For HapResolutions of large groups", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,word) local boundary, letter, letterbound; boundary:=[]; for letter in word do letterbound:=BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,term,letter); boundary:=AddFreeWords(boundary,letterbound); od; return boundary; end); ############################################################################# ## #O BoundaryOfFreeZGWord_LargeGroupRep(,,) #O BoundaryOfFreeZGWord(,,) ## ## Check input and delegate to NC version. ## InstallMethod(BoundaryOfFreeZGWord_LargeGroupRep,"For HapResolution", [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,word) if not IsFreeZGWord_LargeGroupRep(resolution,term,word) then Error(" is not an element of the th module"); fi; return BoundaryOfFreeZGWordNC_LargeGroupRep(resolution,term,word); end); ############################################################################# ## InstallMethod(BoundaryOfFreeZGWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,letter) local word_large; if IsFreeZGWord_LargeGroupRep(resolution,term,letter) then return BoundaryOfFreeZGWordNC_LargeGroupRep(resolution,term,letter); elif IsFreeZGLetter(resolution,term,letter) then word_large:=ConvertWordToStandardRepNC(resolution,term,letter); return ConvertWordToStandardRepNC(resolution,term,BoundaryOfFreeZGWordNC(resolution,term,word_large)); else TryNextMethod(); fi; end); hapcryst-0.2.0/lib/datatypes/resolutionAccess_generic.gd0000644000175100017510000001564315160525022023064 0ustar runnerrunner############################################################################# ## #W resolutionAccess_generic.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## #O PositionInGroupOfResolutionNC(,) ## ## find the position in 's partial list of group elements ## . If is not contained in , it is ## added and the length of is returned. ## DeclareOperation("PositionInGroupOfResolutionNC", [IsHapResolution,IsObject]); ############################################################################# ## #O PositionInGroupOfResolution(,) ## ## find the position in 's partial list of group elements ## . ## This checkes Membership in 's group and then delegates ## to PositionInGroupOfResolutionNC ## DeclareOperation("PositionInGroupOfResolution", [IsHapResolution,IsObject]); ############################################################################# ## #O IsValidGroupInt(,) ## ## test if there are elements of the group of known to the ## (partial) elements list ## DeclareOperation("IsValidGroupInt", [IsHapResolution,IsPosInt]); ############################################################################# ## #O GroupElementFromPosition(,) ## ## returns the th element of 's (partial) list of group ## elements. ## DeclareOperation("GroupElementFromPosition", [IsHapResolution,IsPosInt]); ############################################################################# ## #F MultiplyGroupEltsNC(,,) ## ## multiply two elements of the group associated with . These ## elements are represented as integers or group elements. Depending on ## the kind of resolution they live in. ## Hence, we have different methods for multiplying them. ## DeclareOperation("MultiplyGroupEltsNC", [IsHapResolution,IsPosInt,IsPosInt]); ############################################################################# ## #F MultiplyGroupElts(,,) ## ## Test if the input is sane and then delegate to MultiplyGroupEltsNC ## DeclareOperation("MultiplyGroupElts", [IsHapResolution,IsPosInt,IsPosInt]); ############################################################################# ## #O StrongtestValidRepresentationForLetter(resolution,term,letter) ## ## returns the strongest representation in which is a valid letter ## for ## DeclareOperation("StrongestValidRepresentationForLetter", [IsHapResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O StrongtestValidRepresentationForWord(resolution,term,word) ## ## returns the strongest representation in which is a valid letter ## for ## DeclareOperation("StrongestValidRepresentationForWord", [IsHapResolutionRep,IsInt,IsDenseList]); ############################################################################# ## #O IsFreeZGLetter(,,) ## ## check if is a letter of the th module of . ## A letter is a word of length 1. ## DeclareOperation("IsFreeZGLetter", [IsHapResolution,IsInt,IsDenseList]); ############################################################################# ## #O IsFreeZGWord(,,) ## ## Check if is an element of the th module in ## DeclareOperation("IsFreeZGWord",[IsHapResolution,IsInt,IsDenseList]); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupEltNC(,,) ## ## given a pair of positive integers which represent a generator- ## group element pair, this returns the letter multiplied with the group ## element . ## DeclareOperation("MultiplyFreeZGLetterWithGroupEltNC", [IsHapResolution,IsDenseList,IsPosInt]); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupElt(,,) ## ## Check input for sanity and delegate to NC version ## DeclareOperation("MultiplyFreeZGLetterWithGroupElt", [IsHapResolution,IsDenseList,IsPosInt]); ############################################################################# ## #O MultiplyFreeZGWordWithGroupEltNC(,,) ## ## multiplies the word with the group element . ## No checks are performed. ## DeclareOperation("MultiplyFreeZGWordWithGroupEltNC", [IsHapResolution,IsDenseList,IsPosInt]); ############################################################################# ## #O MultiplyFreeZGWordWithGroupElt(,,) ## ## Check input and delegate to NC version. ## DeclareOperation("MultiplyFreeZGWordWithGroupElt", [IsHapResolution,IsDenseList,IsPosInt]); ############################################################################# ## #O BoundaryOfFreeZGLetterNC(,,) ## ## calculates the boundary of a letter in the th module. ## DeclareOperation("BoundaryOfFreeZGLetterNC", [IsHapResolution,IsInt,IsDenseList]); ############################################################################# ## #O BoundaryOfFreeZGLetter(,,) ## ## checks input and delegates to NC version ## DeclareOperation("BoundaryOfFreeZGLetter", [IsHapResolution,IsInt,IsDenseList]); ############################################################################# ## #O BoundaryOfFreeZGWordNC(,,) ## ## calculate the boundary of the element of the th module of the ## resolution . ## No checks done. ## DeclareOperation("BoundaryOfFreeZGWordNC", [IsHapResolution,IsInt,IsDenseList]); ############################################################################# ## #O BoundaryOfFreeZGWord(,,) ## ## check input and delegate to NC version. ## DeclareOperation("BoundaryOfFreeZGWord", [IsHapResolution,IsInt,IsDenseList]); hapcryst-0.2.0/lib/datatypes/contHomBieberbach.gi0000644000175100017510000002122115160525022021373 0ustar runnerrunner############################################################################# ## #W contHomBieberbach.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## InequalitiesTimesMatrix:=function(ineqs,mat) local dim, inverse, translationPart, returnlist, ineq, returnineq, newv; if not IsAffineMatrixOnRight(mat) then Error("only implemented for matrices on right"); fi; dim:=Size(mat); inverse:=Inverse(LinearPartOfAffineMatOnRight(mat)); translationPart:=mat[dim]{[1..dim-1]}; if inverse=fail then Error("matrix not invertible"); fi; returnlist:=[]; for ineq in ineqs do returnineq:=List(ineq); newv:=inverse*ineq{[2..dim]}; returnineq[1]:=ineq[1]-translationPart*newv; returnineq{[2..dim]}:=newv; Add(returnlist,returnineq); od; return returnlist; end; ############################################################################# TranslatedInequalities:=function(ineqs,trans) local dim, returnineqs, ineq; if not IsVector(trans) then Error("translation must be given as a vector"); fi; dim:=Size(trans); if not Set(ineqs,Size)=[dim+1] then Error("inequalities of wrong size"); fi; returnineqs:=List(ineqs); for ineq in [1..Size(ineqs)] do returnineqs[ineq][1]:=returnineqs[ineq][1]-trans*ineqs[ineq]{[2..Size(trans)+1]}; od; return returnineqs; end; ############################################################################# VectorTimesAffineMatNC:=function(v,mat) local returnvector; returnvector:=Concatenation(v,[1])*mat; return returnvector{[1..Size(v)]}; end; ############################################################################# VectorsTimesAffineMat:=function(vecs,mat) local dim; if not IsAffineMatrixOnRight(mat) then Error(" is not an affine matrix on right"); fi; dim:=Size(mat); if not Set(vecs,Size)=[dim-1] then Error("vectors of wrong form"); fi; return List(vecs,v->VectorTimesAffineMatNC(v,mat)); end; ############################################################################# RelativePositionPointAndInequalities:=function(point,ineqs) local facetpositions, facet, side; facetpositions:=[]; for facet in ineqs do side:=WhichSideOfHyperplane(point,facet); if side=-1 then return "OUTSIDE"; else AddSet(facetpositions,side); fi; od; if facetpositions=[1] then return "INSIDE"; else return "FACET"; fi; end; ############################################################################# coveringOfUnitBox:=function(fudom,boxcenter,group) local dim, vertices, inequalities, pgReps, cover, corner_covered, smallestCorner, boxcorners, cornerbox, g, image, translations, h, cornerTranslations, imageinequalities, trans; Polymake(fudom,"DIM VERTICES FACETS"); dim:=Polymake(fudom,"DIM"); vertices:=Polymake(fudom,"VERTICES"); inequalities:=Polymake(fudom,"FACETS"); pgReps:=PointGroupRepresentatives(group); cover:=[]; corner_covered:=false; ## generate the box to be covered: smallestCorner:=boxcenter-List([1..dim],i->1/2); boxcorners:=Set(smallestCorner+List(Combinations(IdentityMat(dim)),Sum)); RemoveSet(boxcorners,0); AddSet(boxcorners,smallestCorner); cornerbox:=fail; # find all images of the box that intersect with the original one. # This is done by looking at the corners of the box for g in pgReps do image:=Set(vertices,v->VectorTimesAffineMatNC(v,g)); translations:=Union(List(image,v->TranslationsToOneCubeAroundCenter(v,boxcenter))); for h in List(translations,t->g*TranslationOnRightFromVector(t)) do Add(cover,h); if (not corner_covered) and RelativePositionPointAndInequalities(smallestCorner, InequalitiesTimesMatrix(inequalities,h))<>"OUTSIDE" then corner_covered:=true; cornerbox:=h; fi; od; if not corner_covered then cornerTranslations:=Union(List(image,v->TranslationsToOneCubeAroundCenter(v,smallestCorner))); imageinequalities:=InequalitiesTimesMatrix(inequalities,g); while cornerTranslations<>[] and not corner_covered do trans:=Remove(cornerTranslations); if not corner_covered and RelativePositionPointAndInequalities(smallestCorner,TranslatedInequalities(imageinequalities,trans))<>"OUTSIDE" then corner_covered:=true; cornerbox:=g*TranslationOnRightFromVector(trans); Add(cover,cornerbox); fi; od; fi; od; return Set(cover); end; ############################################################################# ## # there should be a way to know if a given disc function # works with a given resolution... # how do I do this? # discFunction:=function(fudom,resolution,contractionCell_groupel) local group, dim, origin, boxcenter, cover, trans, cwSpaceBox, data, disc; group:=GroupOfResolution(resolution); if not IsFundamentalDomainStandardSpaceGroup(fudom,group) then Error("this is not a fundmental domain for this resolution"); fi; Print(".\c"); dim:=DimensionOfMatrixGroup(group)-1; origin:=List([1..dim],i->0); boxcenter:=Concatenation(origin,[1])*contractionCell_groupel; boxcenter:=boxcenter{[1..dim]}; cover:=coveringOfUnitBox(fudom,boxcenter,group)[1]; trans:=TranslationsToOneCubeAroundCenter(origin,boxcenter); trans:=TranslationOnRightFromVector(trans); cwSpaceBox:=SubspaceListFromWord_LargeGroupRep(resolution, dim, [One(GroupRingOfResolution(resolution))] );; data:=rec(cwSpaceBox:=cwSpaceBox,cover:=cover);; disc:=function(resolution,term,letter,data) local zero, gen, ginv, dim, identity, boxcover_thisterm, c, t, transvector, all_translations, i, sign, returnword; if not IsFreeZGLetter_LargeGroupRep(resolution,term,letter) then Error("letter is not a valid ZG letter"); fi; zero:=Zero(GroupRingOfResolution(resolution)); gen:=PositionProperty(letter,i->i<>zero); ginv:=Inverse(CoefficientsAndMagmaElementsAsLists(letter[gen])[2][1]); dim:=Size(g)-1; identity:=IdentityMat(dim); boxcover_thisterm:=Union(List(CoefficientsAndMagmaElementsAsLists(data.cwSpaceBox[term+1][gen])[2],g->List(data.cover,c->g*c))); for c in boxcover_thisterm do t:=ginv*c; #multiplying from the left is right here, # we calculate the inverse translation. if t{[1..dim]}{[1..dim]}=identity then transvector:=-t[dim+1]{[1..dim]}; break; fi; od; Print(transvector); # transvector is a translation which takes into # the covered box space. # This translation may not be unique. But we don't care. # if not ForAll(transvector,IsInt) then Error("translation vector not integer"); fi; all_translations:=[]; for i in [1..dim] do sign:=SignInt(transvector[i]); while transvector[i]<>0 do Add(all_translations,ShallowCopy(transvector)); transvector[i]:=transvector[i]-sign; od; od; all_translations:=Union(all_translations,[List([1..dim],i->0)]); Apply(all_translations,TranslationOnRightFromVector); returnword:=List(data.cwSpaceBox[term+1],i->Sum(all_translations,g->i*g));; return returnword; end; return rec(disc:=disc,disc_data:=data); end;hapcryst-0.2.0/lib/datatypes/resolutionAccess_SmallGroupRep.gd0000644000175100017510000000646215160525022024203 0ustar runnerrunner############################################################################# ## #W resolutionAccess_SmallGroupRep.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## ## This file defines a representation for HapResolutions of small groups. ## ## The additional feature of this representation is the multiplication ## via a multiplication table. ## Also, the list of group elements R!.elts is a set. So we can do binary ## search occasionally. ## ## Elements of the modules in these resolutions are still pairs of integers. ## ## # DeclareRepresentation("IsHapSmallGroupResolutionRep", IsHapResolutionRep, ["dimension", "boundary", "homotopy", "group", "elts", "multtable", "properties"]); HapSmallGroupResolution:=NewType(HapResolutionFamily,IsHapSmallGroupResolutionRep); ############################################################################# ## #O PositionInGroupOfResolutionNC(,) #O PositionInGroupOfResolution(,) ## ## find the position in 's partial list of group elements ## . If is not contained in , it is ## added and the length of is returned. ## DeclareOperation("PositionInGroupOfResolutionNC", [IsHapSmallGroupResolutionRep,IsObject]); DeclareOperation("PositionInGroupOfResolution", [IsHapSmallGroupResolutionRep,IsObject]); ############################################################################# ## #O MultiplyGroupEltsNC(,,) #O MultiplyGroupEltsNC_SmallGroupRep(,,) ## ## multiply two elements of the group associated with . These ## elements are represented as integers or group elements. Depending on ## the kind of resolution they live in. ## Hence, we have different methods for multiplying them. ## DeclareOperation("MultiplyGroupEltsNC", [IsHapSmallGroupResolutionRep,IsPosInt,IsPosInt]); ############################################################################# ## #O MultiplyFreeZGLetterWithGroupEltNC(,,) ## ## given a pair of positive integers which represent a generator- ## group element pair, this returns the letter multiplied with the group ## element . ## This function does not check if the input is sane. ## ## DeclareOperation("MultiplyFreeZGLetterWithGroupEltNC", [IsHapSmallGroupResolutionRep,IsDenseList,IsPosInt]); hapcryst-0.2.0/lib/CWcomplexThings_LargeGroupRep.gi0000644000175100017510000005033415160525022021722 0ustar runnerrunner############################################################################# ## #W CWcomplexThings_LargeGroupRep.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## ## undirectedBoundary calculates just the cells occuring in the boundary. ## signs and multiplicities are ignored. ## InstallMethod(UndirectedBoundaryOfFreeZGLetter_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,cell) if not IsFreeZGLetter_LargeGroupRep(resolution,dim,cell) then Error("invalid letter"); fi; return UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,cell); end); InstallMethod(UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,cell) return Set(BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,cell),i->[AbsInt(i[1]),i[2]]); end); ############################################################################# ## ## undirectedBoundary for words ## InstallMethod(UndirectedBoundaryOfFreeZGWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local boundary_large; if IsFreeZGWord_LargeGroupRep(resolution,dim,word) then return UndirectedBoundaryOfFreeZGWordNC_LargeGroupRep(resolution,dim,word); elif IsFreeZGWord(resolution,dim,word) then boundary_large:=UndirectedBoundaryOfFreeZGWordNC_LargeGroupRep(resolution,dim,ConvertStandardWord(resolution,dim,word)); return ConvertWordToStandardRep(resolution,dim-1,boundary_large); else Error("invalid word"); fi; end); InstallMethod(UndirectedBoundaryOfFreeZGWord_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) if not IsFreeZGWord_LargeGroupRep(resolution,dim,word) then Error("invalid word"); fi; return UndirectedBoundaryOfFreeZGWordNC_LargeGroupRep(resolution,dim,word); end); InstallMethod(UndirectedBoundaryOfFreeZGWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) return Union(List(word,cell->UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,cell))); end); ############################################################################# ## ## InstallMethod(SubspaceListFromWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local spaces_large; if IsFreeZGWord_LargeGroupRep(resolution,dim,word) then spaces_large:=SubspaceListFromWordNC_LargeGroupRep(resolution,dim,word); elif IsFreeZGWord(resolution,dim,word) then spaces_large:=SubspaceListFromWordNC_LargeGroupRep(resolution, dim, ConvertStandardWord(resolution,dim,word) ); else Error(" is not a valid word"); fi; return List([0..Size(spaces_large)-1], i->ConvertWordToStandardRep(resolution,i,spaces_large[i+1])); end); InstallMethod(SubspaceListFromWord_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) if IsFreeZGWord_LargeGroupRep(resolution,dim,word) then return SubspaceListFromWordNC_LargeGroupRep(resolution,dim,word); else Error(" is not a valid word in large group representation"); fi; end); InstallMethod(SubspaceListFromWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local subspaces, i; subspaces:=List([0..dim],i->[]); subspaces[dim+1]:=Set(word,i->[AbsInt(i[1]),i[2]]); for i in [dim-1,dim-2..0] do # subspaces[i+1]:=Union(List(subspaces[i+2], # j->UndirectedBoundaryOfFreeZGLetter_LargeGroupRep(resolution,i+1,j)) # ); subspaces[i+1]:=UndirectedBoundaryOfFreeZGWord_LargeGroupRep(resolution,i+1,subspaces[i+2]); od; return subspaces; end); ############################################################################# ## ## Tests if a word represents a connected supspace. ## InstallMethod(IsConnectedWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local converted_word; if IsFreeZGWord_LargeGroupRep(resolution,dim,word) then return IsConnectedWordNC_LargeGroupRep(resolution,dim,word); elif IsFreeZGWord(resolution,dim,word) then converted_word:=ConvertStandardWord(resolution,dim,word); return IsConnectedWordNC_LargeGroupRep(resolution,dim,converted_word); else Error("invalid input"); fi; end); InstallMethod(IsConnectedWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local lettersAndBound, startblob, blobbound, addToBlob, addToBlobBound; lettersAndBound:=Set(word,letter-> [letter,UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,letter)] ); # a "blob" is just that. A connected part of . # We don't generate the blob. As we are just interesed in it's size. startblob:=Remove(lettersAndBound); blobbound:=startblob[2]; repeat addToBlob:=Filtered(lettersAndBound,i->Intersection(i[2],blobbound)<>[]); if addToBlob<>[] then SubtractSet(lettersAndBound,addToBlob); addToBlobBound:=Union(List(addToBlob,i->i[2])); blobbound:=Union(blobbound,addToBlobBound); fi; until lettersAndBound=[] or addToBlob=[]; if lettersAndBound=[] then return true; elif addToBlob=[] then return false; fi; end); ############################################################################# ## ## connect a cell to the subspace . ## InstallMethod(ConnectingPath, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList], function(resolution,dim,area,cellblob,cell) local cell_large, cellblob_large, area_large, path_large; if IsFreeZGLetter(resolution,dim,cell) then cell_large:=ConvertStandardLetter(resolution,dim,cell); cellblob_large:=ConvertStandardWord(resolution,dim,cellblob); area_large:=ConvertStandardWord(resolution,dim,area); path_large:=ConnectingPathNC_LargeGroupRep(resolution, dim, area_large, cellblob_large, cell_large ); if path_large=fail then return fail; else return ConvertWordToStandardRep(resolution,dim,path_large); fi; elif IsFreeZGLetter_LargeGroupRep(resolution,dim,cell) then path_large:=ConnectingPath_LargeGroupRep(resolution, dim, area, cellblob, cell ); return path_large; else TryNextMethod(); fi; end); ############################################################################# ## InstallMethod(ConnectingPath_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList], function(resolution,dim,area,cellblob,cell) if not (IsFreeZGWord_LargeGroupRep(resolution,dim,area) and IsFreeZGWord_LargeGroupRep(resolution,dim,cellblob) ) then Error(" and must be valid words"); elif not IsFreeZGLetter_LargeGroupRep(resolution,dim,cell) then Error(" is not a valid letter"); elif not IsSubset(area,cellblob) and cell in area then Error(" does not contain and "); fi; return ConnectingPathNC_LargeGroupRep(resolution,dim,area,cellblob,cell); end); ############################################################################# ## InstallMethod(ConnectingPathNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList], function(resolution,dim,area,cellblob,cell) local pathfinder, sphereAndBounds, path; ################################################## ## ## The recursive function "pathfinder" assumes that connectTo is not empty. ## It calculates a path from a "disk" that connects a given starting part ## with the space of known homotopies. ## pathfinder:=function(resolution, connectTo, sphereAndBounds, startingBit,startingbitboundary) local thingsThatCouldBeAdded, endpoint, addface, newSphereAndBounds, newstartingbitboundary, newstartingBit, returnpath; thingsThatCouldBeAdded:=Filtered(sphereAndBounds,i->Intersection(i[2],startingbitboundary)<>[]); endpoint:=First(thingsThatCouldBeAdded,i->Intersection(i[2],connectTo)<>[]); if endpoint<>fail then return Concatenation(startingBit,[endpoint[1]]); else newSphereAndBounds:=Difference(sphereAndBounds,thingsThatCouldBeAdded); repeat if thingsThatCouldBeAdded=[] then return []; fi; addface:=Remove(thingsThatCouldBeAdded); newstartingbitboundary:=Union(startingbitboundary,addface[2]); newstartingBit:=Concatenation(startingBit,[addface[1]]); returnpath:=pathfinder(resolution, connectTo, newSphereAndBounds, newstartingBit, newstartingbitboundary ); until returnpath<>[]; return Unique(returnpath); fi; end; if cell in cellblob then return []; fi; sphereAndBounds:=Set(area,i->[i,UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,i)]); path:=pathfinder(resolution, # undirectedReducedBoundaryOfWord(resolution,dim,cellblob), UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,cell), sphereAndBounds, [cell], UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,cell) ); if path=[] then return fail; else return path; fi; end); ############################################################################# ## ## given a word in the th term of , this returns true ## if and only if this word represents a contractible subspace. ## ## connectedness is not tested. ## Is this right, anyway? ## InstallMethod(IsContractibleWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,subspace) local chaincomplex, i; chaincomplex:=ChainComplexFromWordNC_LargeGroupRep(resolution,dim,subspace); return Homology(chaincomplex,dim)=[]; end); ############################################################################# ## InstallMethod(IsContractibleWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,subspace) local converted_subspace; if IsFreeZGWord_LargeGroupRep(resolution,dim,subspace) then return IsContractibleWordNC_LargeGroupRep(resolution,dim,subspace); elif IsFreeZGWord(resolution,dim,subspace) then converted_subspace:=ConvertWordToStandardRep(resolution,dim,subspace); return IsContractibleWordNC(resolution,dim,converted_subspace); else Error("invalid input"); fi; end); ############################################################################# ## ## InstallMethod(IsContractiblePartialSpace, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,spacelist) local spacelist_large; if ForAll(spacelist,subspace->IsFreeZGWord_LargeGroupRep(resolution,dim,subspace)) then return IsContractiblePartialSpaceNC_LargeGroupRep(resolution,dim,spacelist); elif ForAll(spacelist,subspace->IsFreeZGWord(resolution,dim,subspace)) then spacelist_large:=List(spacelist,space->ConvertStandardWord(resolution,dim,space)); return IsContractiblePartialSpaceNC_LargeGroupRep(resolution,dim,spacelist_large); else Error("subspacelist does not consist of valid words"); fi; end); ############################################################################# ## InstallMethod(IsContractiblePartialSpaceNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,spacelist) local chaincomplex; chaincomplex:=ChainComplexFromPartialSpaceNC_LargeGroupRep(resolution,spacelist); return Homology(chaincomplex,dim)=[]; end); ############################################################################# ## ## find the sphere that contains . ## The list of cells must induce a chain complex with th ## homology [0]. ## ############################################################################# ## ## check the input and delegate... ## InstallMethod(SphereContainingCell, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList], function(resolution,dim,space,cell) local complex; if not IsFreeZGLetter_LargeGroupRep(resolution,dim,cell) then Error(" is not a valid letter"); elif not IsFreeZGWord_LargeGroupRep(resolution,dim,space) then Error(" is not a valid word"); elif not cell in space then Error(" not in "); fi; complex:=ChainComplexFromWordNC_LargeGroupRep(resolution,dim,space); if not Homology(complex,dim)=[0] then Error(" does not contain a unique sphere"); fi; return SphereContainingCellNC_LargeGroupRep(resolution,dim,space,cell); end); InstallMethod(SphereContainingCell_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList], function(resolution,dim,space,cell) local complex; if not IsFreeZGLetter_LargeGroupRep(resolution,dim,cell) then Error(" is not a valid letter"); elif not IsFreeZGWord_LargeGroupRep(resolution,dim,space) then Error(" is not a valid word"); elif not cell in space then Error(" not in "); fi; complex:=ChainComplexFromWordNC_LargeGroupRep(resolution,dim,space); if not Homology(complex,dim)=[0] then Error(" does not contain a unique sphere"); fi; return SphereContainingCellNC_LargeGroupRep(resolution,dim,space,cell); end); ############################################################################# ## ## InstallMethod(SphereContainingCellNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList], function(resolution,dim,space,cell) local space_and_bounds, sphere, spherebound, sphere_done, subspacelist, complex, newcells, new_subspaces, i; space_and_bounds:=List(space,i->[i,UndirectedBoundaryOfFreeZGWord(resolution,dim,i)]); sphere:=[cell]; spherebound:=UndirectedBoundaryOfFreeZGWord_LargeGroupRep(resolution,dim,sphere); sphere_done:=false; subspacelist:=SubspaceListFromWord_LargeGroupRep(resolution,dim,sphere); complex:=ChainComplexFromPartialSpace(resolution, subspacelist ); while not Homology(complex,dim)=[0] do newcells:=Filtered(space_and_bounds,c->ForAny(c[2],i->i in spherebound)); SubtractSet(space_and_bounds,newcells); UniteSet(sphere,List(newcells,i->i[1])); UniteSet(spherebound,Concatenation(List(newcells,i->i[2]))); new_subspaces:=SubspaceListFromWordNC_LargeGroupRep(resolution, dim, List(newcells,i->i[1]) ); for i in [1..Size(new_subspaces)] do UniteSet(subspacelist[i],new_subspaces[i]); od; od; return Set(sphere); end); ############################################################################# ## ## Generate a chain complex from a word ## InstallMethod(ChainComplexFromWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,subspace) local converted_subspace; if IsFreeZGWord_LargeGroupRep(resolution,dim,subspace) then return ChainComplexFromWordNC_LargeGroupRep(resolution,dim,subspace); elif IsFreeZGWord(resolution,dim,subspace) then converted_subspace:=ConvertWordToStandardRep(resolution,dim,subspace); return ChainComplexFromWordNC(resolution,dim,subspace); else Error("invalid input"); fi; end); InstallMethod(ChainComplexFromWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,subspace) local spaces; spaces:=SubspaceListFromWordNC_LargeGroupRep(resolution,dim,subspace); return ChainComplexFromPartialSpaceNC_LargeGroupRep(resolution,spaces); end); ############################################################################# ## ## Generate a chain complex from a list of words ## InstallMethod(ChainComplexFromPartialSpace_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsDenseList], function(resolution,subspaces) if not ForAll([1..Size(subspaces)],dim-> IsFreeZGWord_LargeGroupRep(resolution,dim-1,subspaces[dim]) ) then Error("subspace list contains invalid words"); fi; return ChainComplexFromPartialSpaceNC_LargeGroupRep(resolution,subspaces); end); InstallMethod(ChainComplexFromPartialSpaceNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsDenseList], function(resolution,subspaces) local undirectedLetter, word2vec, boundary, dimension, complex, properties; undirectedLetter:=function(letter) return [AbsInt(letter[1]),letter[2]]; end; word2vec:=function(generators,word) local vec, letter, pos; vec:=List([1..Size(generators)],i->0); for letter in word do pos:=Position(generators,undirectedLetter(letter)); if pos<>fail then vec[pos]:=vec[pos]+SignInt(letter[1]); else Error("word-vector conversion error"); fi; od; return vec; end; boundary:=function(k,j) local letter, boundaryAsWord; if k=Size(subspaces+1) then return []; fi; letter:=subspaces[k+1][j]; boundaryAsWord:=BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,k,letter); return word2vec(subspaces[k],boundaryAsWord); end; dimension:=function(k) if k) ## InstallMethod(ResolutionBieberbachGroup, [IsGroup], function(group) return ResolutionBieberbachGroup(group,0*[1..Size(Representative(group))-1]); end); ############################################################################# ## #O ResolutionBieberbachGroup(,
) ## InstallMethod(ResolutionBieberbachGroup,"for affine cryst groups on right", [IsGroup,IsVector], function(group,center) local gram, poly, fl; gram:=GramianOfAverageScalarProductFromFiniteMatrixGroup(PointGroup(group)); if not Order(gram)=1 then Info(InfoHAPcryst,2,"non standard"); fi; poly:=FundamentalDomainBieberbachGroup(center,group,gram); fl:=FaceLatticeAndBoundaryBieberbachGroup(poly,group); RemoveFile(FullFilenameOfPolymakeObject(poly)); return ResolutionFromFLandBoundary(fl, group); end); ############################################################################# ## #O ResolutionFromFLandBoundary(,) ## InstallMethod(ResolutionFromFLandBoundary,"for affine cryst groups on right", [IsRecord,IsGroup], function(fl,group) local dimension, dimension2, boundary, elts, appendToElts, boundary2, groupring, resolution, homotopy, hasse, properties; dimension:=function(k) if k<0 or k>Size(fl.hasse)-1 then return 0; else return Size(fl.hasse[k+1]); fi; end; dimension2:=function(resolution,k) if k<0 or k>Size(resolution!.hasse)-1 then return 0; else return Size(resolution!.hasse[k+1]); fi; end; boundary:=function(k,j) local word, jsign, stdword, pos, coeffsAndGroupElts, g, sign, mult, entry, i; if k<=0 or k>=Size(fl.hasse) then return []; else word:=fl.hasse[k+1][AbsInt(j)][2]; jsign:=SignInt(j); stdword:=[]; for pos in [1..Size(word)] do coeffsAndGroupElts:=CoefficientsAndMagmaElementsAsLists(word[pos][2]); for g in [1..Size(coeffsAndGroupElts[1])] do sign:=jsign*SignInt(coeffsAndGroupElts[1][g]); mult:=AbsInt(coeffsAndGroupElts[1][g]); entry:=[sign*word[pos][1],Position(fl.elts,coeffsAndGroupElts[2][g])]; for i in [1..mult] do Add(stdword,entry); od; od; od; fi; return stdword; end; ## this is the usual HAP trick. ## After the termination of ResolutionFromFLandBoundary, will not ## be collected by GASMAN because appendToElts still uses it. ## It will just float around as a secret global (to appendToElts) ## variable... ## ## same with . ## elts:=StructuralCopy(fl.elts); appendToElts:=function(g) if not g in group then Error("not an element of the right group"); fi; Add(elts,g); end; ################################################## ################################################## boundary2:=function(resolution,k,j) local zero, family, vector, term; if k<=0 or k>=Size(resolution!.hasse) then return []; else zero:=Zero(resolution!.groupring); family:=FamilyObj(zero); vector:=List([1..Dimension(resolution)(k-1)],i->zero); for term in resolution!.hasse[k+1][j][2] do vector[term[1]]:=vector[term[1]]+ term[2]; od; fi; return vector; end; if not (IsAffineCrystGroupOnRight(group) and IsStandardSpaceGroup(group)) then Error("group is not a StandardSpaceGroup acting on right"); fi; if not ForAll(fl.elts,i->i in group) then Error("group does not match face lattice"); fi; groupring:=fl.groupring; resolution:=Objectify(HapLargeGroupResolution, rec( groupring:=groupring, dimension:=dimension, dimension2:=dimension2, boundary:=boundary, boundary2:=boundary2, homotopy:=fail, elts:=elts, appendToElts:=appendToElts, group:=group, hasse:=fl.hasse, properties:= [["length",Size(fl.hasse)], ["type","resolution"], ["characteristic",0] ] )); return resolution; end); hapcryst-0.2.0/lib/resolutionBieberbach.gd0000644000175100017510000000230015160525022020161 0ustar runnerrunner############################################################################# ## #W resolutionBieberbach.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## DeclareOperation("ResolutionBieberbachGroup",[IsGroup]); DeclareOperation("ResolutionBieberbachGroup",[IsGroup,IsVector]); DeclareOperation("FaceLatticeAndBoundaryBieberbachGroup",[IsPolymakeObject,IsGroup]); DeclareOperation("ResolutionFromFLandBoundary",[IsRecord,IsGroup]); hapcryst-0.2.0/lib/GroupRing.gi0000644000175100017510000000417315160525022015762 0ustar runnerrunner############################################################################# ## #W GroupRing.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## #O CoefficientsAndMagmaElementsAsLists ## ## just a function that behaves as expected... ## InstallMethod(CoefficientsAndMagmaElementsAsLists, [IsElementOfFreeMagmaRing], function(elt) local coeffsAndMagmaElts, length; coeffsAndMagmaElts:=CoefficientsAndMagmaElements(elt); if coeffsAndMagmaElts=[] then return [[],[]]; else length:=Size(coeffsAndMagmaElts)/2; return [List(2*[1..length],i->coeffsAndMagmaElts[i]), List(2*[1..length]-1,i->coeffsAndMagmaElts[i]) ]; fi; end); InstallMethod(Indicator,"for magma ring with one", [IsElementOfFreeMagmaRing], function(elm) local zero, coeffs, one; zero:=ZeroCoefficient(elm); if not IsMultiplicativeElementWithOne(zero) then Error("Ring of magma ring must have a one"); else coeffs:=CoefficientsAndMagmaElementsAsLists(elm); if coeffs[1]=[] then return elm; else one:=zero^0; coeffs[1]:=List(coeffs[1],i->one); return ElementOfMagmaRing(FamilyObj(elm),zero,coeffs[1],coeffs[2]); fi; fi; end); hapcryst-0.2.0/lib/GroupRing.gd0000644000175100017510000000207715160525022015756 0ustar runnerrunner############################################################################# ## #W GroupRing.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## DeclareOperation("CoefficientsAndMagmaElementsAsLists", [IsElementOfFreeMagmaRing]); DeclareOperation("Indicator", [IsElementOfFreeMagmaRing]); hapcryst-0.2.0/lib/environment.gd0000644000175100017510000000167315160525022016407 0ustar runnerrunner############################################################################# ## #W environment.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## DeclareInfoClass("InfoHAPcryst"); hapcryst-0.2.0/lib/FundamentalDomain.gi0000644000175100017510000001533115160525022017432 0ustar runnerrunner############################################################################# ## #W FundamentalDomain.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## #O FundamentalDomainStandardSpaceGroup ## InstallMethod(FundamentalDomainStandardSpaceGroup, [IsGroup], function(group) local dim; if not (IsStandardSpaceGroup(group) and IsAffineCrystGroupOnRight(group)) then Error("group must be a StandardSpaceGroup acting on right"); fi; dim:=DimensionOfMatrixGroup(group)-1; return FundamentalDomainStandardSpaceGroup(0*[1..dim],group); end); ############################################################################# ## #O FundamentalDomainStandardSpaceGroup ## InstallMethod(FundamentalDomainStandardSpaceGroup, [IsVector,IsGroup], function(center,group) local dim, gram, orbitstab; if not (IsStandardSpaceGroup(group) and IsAffineCrystGroupOnRight(group)) then Error("group must be a StandardSpaceGroup acting on right"); fi; dim:=Size(Representative(group))-1; gram:=GramianOfAverageScalarProductFromFiniteMatrixGroup( PointGroup(group)); if not IsTrivial(StabilizerOnSetsStandardSpaceGroup(group,[center])) then Error("center point not in general position"); fi; return FundamentalDomainBieberbachGroupNC(center,group,gram); end); ############################################################################# ## #O IsFundamentalDomainStandardSpaceGroup ## InstallMethod(IsFundamentalDomainStandardSpaceGroup, [IsPolymakeObject,IsGroup], function(poly,group) local vertices, vertexset, dim, box, vertex, orbitstab, orbitpart, i, j, facets, polystab, facet, orbit, facetstab, staborbit; if not (IsStandardSpaceGroup(group) and IsAffineCrystGroupOnRight(group)) then Error("group must be a StandardSpaceGroup acting on right"); fi; vertices:=Polymake(poly,"VERTICES"); vertexset:=Set(vertices); dim:=Size(Representative(vertices)); ### First check that the images of do not overlap: box:=List([1..dim],i->[Minimum(List(vertices,v->v[i])),Maximum(List(vertices,v->v[i]))]); while vertexset<>[] do vertex:=Remove(vertexset); orbitstab:=OrbitStabilizerInUnitCubeOnRight(group,VectorModOne(vertex)); # orbitpart:=Concatenation(List(orbitstab.orbit,i->List(TranslationsToBox(i,box),j->i+j))); orbitpart:=[]; for i in orbitstab.orbit do for j in TranslationsToBox(i,box) do Add(orbitpart,i+j); od; od; if ForAny(orbitpart,v->RelativePositionPointAndPolygon(v,poly) in ["INSIDE","FACET"]) then return false; else SubtractSet(vertexset,orbitpart); fi; od; ### Now find out if the orbit covers the whole space. ### For this, we check whether every facet "has an image of the fundamental domain ### on either side": vertexset:=Set(vertices); facets:=Set(Polymake(poly,"VERTICES_IN_FACETS"),i->Set(i,j->vertices[j])); polystab:=StabilizerOnSetsStandardSpaceGroup(group,Set(vertices)); while facets<>[] do facet:=facets[1]; orbit:=OrbitPartInVertexSetsStandardSpaceGroup(group,facet,vertexset); if not ForAll(orbit,i-> i in facets) then return false; fi; if Size(polystab)=1 then if Size(orbit)=1 then facetstab:=StabilizerOnSetsStandardSpaceGroup(group,facet); if Size(facetstab)=1 then #no image of can be on the other side of . # If <>1, it contains an element flipping # to the other side of . return false; fi; #If |orbit|>1, there must be another facet f' which gets mapped to # . As polystab=1, this maps tho the opposite side of # . So we are done in this case. fi; else staborbit:=Orbit(polystab,Set(facet,i->Concatenation(i,[1])),OnSets); # now there are two kinds of facets in : # 1. those which are images under polystab # 2. the other ones. ## The second ones are ok. For the other ones, we have to ## check if there is an element of the facet stabilizer ## swapping to the other side of . if Size(staborbit) is not a valid word"); fi; return UndirectedWordNC_LargeGroupRep(resolution,word); end); ############################################################################# ## InstallMethod(UndirectedWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsDenseList], function(resolution,word) local fam, returnword, term, coeffs, i; fam:=FamilyObj(Zero(GroupRingOfResolution(resolution))); returnword:=[]; for term in [1..Size(word)] do coeffs:=CoefficientsAndMagmaElementsAsLists(word[term]); for i in [1..Size(coeffs[1])] do if coeffs[1][i]<>0 then coeffs[1][i]:=1; fi; od; returnword[term]:=ElementOfMagmaRing(fam,0,coeffs[1],coeffs[2]); od; return returnword; end); ############################################################################# ## InstallMethod(IsUndirectedWord_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsDenseList], function(resolution,word) local zero, term; if not IsFreeZGWordNoTermCheck_LargeGroupRep(resolution,word) then return false; fi; zero:=Zero(GroupRingOfResolution(resolution)); for term in word do if term<>zero then if not Set(CoefficientsAndMagmaElementsAsLists(term)[1])=[1] then return false; fi; fi; od; return true; end); ############################################################################# ## InstallMethod(IsUndirectedWord_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,term,word) local zero; if not IsFreeZGWord_LargeGroupRep(resolution,term,word) then return false; fi; zero:=Zero(GroupRingOfResolution(resolution)); for term in word do if term<>zero then if not Set(CoefficientsAndMagmaElementsAsLists(term)[1])=[1] then return false; fi; fi; od; return true; end); ############################################################################# ## #O OneCoefficientPartOfWord ## ## just the parts parts of the ZG elements with coefficient=1. ## This can be used to calculate "intersections" of undirected words. ## InstallMethod(OneCoefficientPartOfWord_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsVector], function(resolution,word) if not IsFreeZGWordNoTermCheck_LargeGroupRep(resolution,word) then Error(" is not valid"); fi; return OneCoefficientPartOfWordNC_LargeGroupRep(resolution,word); end); ############################################################ InstallMethod(OneCoefficientPartOfWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsVector], function(resolution,word) local returnword, zero, one, fam, term, coeffs, i; returnword:=ShallowCopy(word); zero:=Zero(GroupRingOfResolution(resolution)); one:=ZeroCoefficient(zero)^0; fam:=FamilyObj(zero); for term in [1..Size(word)] do if word[term]<>zero then coeffs:=CoefficientsAndMagmaElementsAsLists(word[term]); for i in [1..Size(coeffs[1])] do if coeffs[1][i]<>one then Unbind(coeffs[1][i]); Unbind(coeffs[2][i]); fi; od; returnword[term]:=ElementOfMagmaRing(fam,0,Compacted(coeffs[1]),Compacted(coeffs[2])); fi; od; return returnword; end); ############################################################################# ## #O IntersectingUndirectedWords_LargeGroupRep ## ## returns true if and have a non-trivial intersection. ## The words have to be undirected. Otherwise the intersection is not defined. ## InstallMethod(IntersectingUndirectedWords_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsDenseList,IsDenseList], function(resolution,word1,word2) if not Size(word1)=Size(word2) then Error("words of different length"); elif not (IsUndirectedWord_LargeGroupRep(resolution,word1) and IsUndirectedWord_LargeGroupRep(resolution,word2) ) then Error(" and must be valid words"); fi; return IntersectingUndirectedWordsNC_LargeGroupRep(resolution,word1,word2); end); ############################################################################# ## InstallMethod(IntersectingUndirectedWordsNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsDenseList,IsDenseList], function(resolution,word1,word2) local zero, term, gElts1, gElts2; zero:=Zero(GroupRingOfResolution(resolution)); for term in [1..Size(word1)] do if word1[term]<>zero and word2[term]<>zero then gElts1:=CoefficientsAndMagmaElementsAsLists(word1[term])[2]; gElts2:=Set(CoefficientsAndMagmaElementsAsLists(word2[term])[2]); if ForAny(gElts1,i->i in gElts2) then return true; fi; fi; od; return false; end); ############################################################################# ## InstallMethod(IsUndirectedSubWord_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsDenseList,IsDenseList], function(resolution,word1,word2) if IsUndirectedWord_LargeGroupRep(resolution,word1) and IsUndirectedWord_LargeGroupRep(resolution,word2) then return IsUndirectedSubWordNC_LargeGroupRep(resolution,word1,word2); else Error("words must be undirected words of "); fi; end); ############################################################################# ## InstallMethod(IsUndirectedSubWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsDenseList,IsDenseList], function(resolution,word1,word2) local term, groupelts1, groupelts2; if Size(word1)<>Size(word2) then return false; else for term in [1..Size(word1)] do groupelts1:=CoefficientsAndMagmaElementsAsLists(word1[term])[2]; groupelts2:=CoefficientsAndMagmaElementsAsLists(word2[term])[2]; if not IsSubset(groupelts1,groupelts2) then return false; fi; od; fi; return true; end); ############################################################################# ## ## undirectedBoundary calculates just the cells occuring in the boundary. ## signs and multiplicities are ignored. ## InstallMethod(UndirectedBoundaryOfFreeZGLetter_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,cell) if not IsFreeZGLetter_LargeGroupRep(resolution,dim,cell) then Error("invalid letter"); fi; return UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,cell); end); ############################################################################# ## InstallMethod(UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,cell) local zero, fam, boundary, term, coeffsAndGroupElts, coeffs; zero:=Zero(GroupRingOfResolution(resolution)); fam:=FamilyObj(zero); boundary:=BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,cell); return UndirectedWord_LargeGroupRep(resolution,boundary); # for term in [1..Size(boundary)] do # if term<>zero then # coeffsAndGroupElts:=CoefficientsAndMagmaElementsAsLists(boundary[term]); # coeffs:=coeffsAndGroupElts[1]; # Apply(coeffs,function(i) if i<>0 then return 1; else return 0; fi; end); # boundary[term]:=ElementOfMagmaRing(fam,0,coeffs,coeffsAndGroupElts[2]); # fi; # od; # return boundary; end); ############################################################################# ## ## undirectedBoundary for words. ## This does NOT calculate the boundary and then kills all the multiplicities. ## It calculates all dim-1 faces which touch the word . ## InstallMethod(UndirectedBoundaryOfFreeZGWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local boundary_large; if IsFreeZGWord_LargeGroupRep(resolution,dim,word) then return UndirectedBoundaryOfFreeZGWordNC_LargeGroupRep(resolution,dim,word); elif IsFreeZGWord(resolution,dim,word) then boundary_large:=UndirectedBoundaryOfFreeZGWordNC_LargeGroupRep(resolution,dim,ConvertStandardWord(resolution,dim,word)); return ConvertWordToStandardRep(resolution,dim-1,boundary_large); else Error("invalid word"); fi; end); ############################################################################# ## InstallMethod(UndirectedBoundaryOfFreeZGWord_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) if not IsFreeZGWord_LargeGroupRep(resolution,dim,word) then Error("invalid word"); fi; return UndirectedBoundaryOfFreeZGWordNC_LargeGroupRep(resolution,dim,word); end); ############################################################################# ## InstallMethod(UndirectedBoundaryOfFreeZGWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local zero, fam, boundary, term, thistermbound; zero:=Zero(GroupRingOfResolution(resolution)); fam:=FamilyObj(zero); boundary:=[]; for term in [1..Size(word)] do if word[term]<>zero then thistermbound:=BoundaryOfGenerator_LargeGroupRep(resolution,dim,term); boundary:=boundary+UndirectedWord_LargeGroupRep(resolution,thistermbound)*word[term]; fi; od; return UndirectedWord_LargeGroupRep(resolution,boundary); end); ############################################################################# ## InstallMethod(LowerSpaceFromWord_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList], function(resolution,term,word,lowerterms) local lowerspaceparts, zero, one, zerovec, thisterm, i, lowerspace, position, returnspaces, lsp, returnspace, thispart; if not (IsSet(lowerterms) and ForAll(lowerterms,i->IsInt(i) and i>=0)) then Error(" must be a set of non-negative integers"); fi; if termList([1..Size(word)],i->[])); zero:=Zero(GroupRingOfResolution(resolution)); one:=zero^0; zerovec:=ListWithIdenticalEntries(Size(word),zero); thisterm:=term; for i in [1..Size(word)] do lowerspace:=ShallowCopy(zerovec); lowerspace[i]:=one; while thisterm>Minimum(lowerterms) do lowerspace:=UndirectedBoundaryOfFreeZGWord_LargeGroupRep(resolution,thisterm,lowerspace); thisterm:=thisterm-1; if thisterm in lowerterms then position:=Position(lowerterms,thisterm); lowerspaceparts[position][i]:=lowerspace; fi; od; od; Info(InfoHAPcryst,2,"template done"); returnspaces:=[]; for lsp in [1..Size(lowerterms)] do Info(InfoHAPcryst,2,"dimension ",lowerterms[lsp]); if lowerterms[lsp]=term then returnspace:=word; else returnspace:=ListWithIdenticalEntries(Size(lowerspaceparts[lsp]),zero); for i in [1..Size(word)] do thispart:=lowerspaceparts[lsp][i]; returnspace:=returnspace+List(thispart,x->x*word[i]); od; fi; returnspace:=UndirectedWord_LargeGroupRep(resolution,returnspace); Add(returnspaces,returnspace); od; return returnspaces; end); ############################################################################# ## ## InstallMethod(SubspaceListFromWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local spaces_large; if IsFreeZGWord_LargeGroupRep(resolution,dim,word) then spaces_large:=SubspaceListFromWordNC_LargeGroupRep(resolution,dim,word); return spaces_large; elif IsFreeZGWord(resolution,dim,word) then spaces_large:=SubspaceListFromWordNC_LargeGroupRep(resolution, dim, ConvertStandardWord(resolution,dim,word) ); return List([0..Size(spaces_large)-1], i->ConvertWordToStandardRep(resolution,i,spaces_large[i+1])); else Error(" is not a valid word"); fi; end); ############################################################################# ## InstallMethod(SubspaceListFromWord_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) if IsFreeZGWord_LargeGroupRep(resolution,dim,word) then return SubspaceListFromWordNC_LargeGroupRep(resolution,dim,word); else Error(" is not a valid word in large group representation"); fi; end); ############################################################################# ## InstallMethod(SubspaceListFromWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local subspaces, i; subspaces:=List([0..dim],i->[]); subspaces[dim+1]:=UndirectedWord_LargeGroupRep(resolution,word); for i in [dim-1,dim-2..0] do subspaces[i+1]:=UndirectedBoundaryOfFreeZGWordNC_LargeGroupRep(resolution,i+1,subspaces[i+2]); od; return subspaces; end); ############################################################################# ## ## Tests if a word represents a connected supspace. ## InstallMethod(IsConnectedWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local converted_word; if IsFreeZGWord_LargeGroupRep(resolution,dim,word) then return IsConnectedWordNC_LargeGroupRep(resolution,dim,word); elif IsFreeZGWord(resolution,dim,word) then converted_word:=ConvertStandardWord(resolution,dim,word); return IsConnectedWordNC_LargeGroupRep(resolution,dim,converted_word); else Error("invalid input"); fi; end); ############################################################################# ## InstallMethod(IsConnectedWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local zero, fam, zerovec, lettersAndBound, term, groupels, g, letter, startblob, blobbound, addToBlob, addToBlobBound; zero:=Zero(GroupRingOfResolution(resolution)); fam:=FamilyObj(zero); zerovec:=List([1..Size(word)],i->zero); lettersAndBound:=[]; for term in [1..Size(word)] do if word[term]<>zero then groupels:=CoefficientsAndMagmaElementsAsLists(word[term])[2]; for g in groupels do letter:=ShallowCopy(zerovec); letter[term]:=ElementOfMagmaRing(fam,0,[1],[g]); Add(lettersAndBound,[letter, UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,letter)] ); od; fi; od; lettersAndBound:=Set(lettersAndBound); # a "blob" is just that. A connected part of . # We don't generate the blob. As we are just interesed in it's size. startblob:=Remove(lettersAndBound); blobbound:=startblob[2]; repeat addToBlob:=Filtered(lettersAndBound,i-> IntersectingUndirectedWordsNC_LargeGroupRep(resolution,i[2],blobbound) ); if addToBlob<>[] then SubtractSet(lettersAndBound,addToBlob); addToBlobBound:=Sum(List(addToBlob,i->i[2])); blobbound:=UndirectedWord_LargeGroupRep(resolution,blobbound+addToBlobBound); fi; until lettersAndBound=[] or addToBlob=[]; if lettersAndBound=[] then return true; elif addToBlob=[] then return false; fi; end); ############################################################################# ## ## connect a cell to the subspace . ## InstallMethod(ConnectingPath, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList], function(resolution,dim,area,cellblob,cell) local cell_large, cellblob_large, area_large, path_large; if IsFreeZGLetter(resolution,dim,cell) then cell_large:=ConvertStandardLetter(resolution,dim,cell); cellblob_large:=ConvertStandardWord(resolution,dim,cellblob); area_large:=ConvertStandardWord(resolution,dim,area); path_large:=ConnectingPathNC_LargeGroupRep(resolution, dim, area_large, cellblob_large, cell_large ); if path_large=fail then return fail; else return ConvertWordToStandardRep(resolution,dim,path_large); fi; elif IsFreeZGLetter_LargeGroupRep(resolution,dim,cell) then path_large:=ConnectingPath_LargeGroupRep(resolution, dim, area, cellblob, cell ); return path_large; else TryNextMethod(); fi; end); ############################################################################# ## InstallMethod(ConnectingPath_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList], function(resolution,dim,area,cellblob,cell) if not (IsUndirectedWord_LargeGroupRep(resolution,area) and IsFreeZGWord_LargeGroupRep(resolution,dim,cellblob) ) then Error(" and must be undirected words"); elif not (IsFreeZGLetter_LargeGroupRep(resolution,dim,cell) and IsUndirectedWord_LargeGroupRep(resolution,cell) ) then Error(" is not a valid undirected letter"); elif not IsUndirectedSubWordNC_LargeGroupRep(resolution,area,cellblob) and cell in area then Error(" does not contain and "); fi; return ConnectingPathNC_LargeGroupRep(resolution,dim,area,cellblob,cell); end); ############################################################################# ## InstallMethod(ConnectingPathNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList], function(resolution,dim,area,cellblob,cell) local pathfinder, zero, fam, zerovec, sphereAndBounds, term, groupels, g, letter, path; ################################################## ## ## The recursive function "pathfinder" assumes that connectTo is not empty. ## It calculates a path from a "disk" that connects a given starting part ## with the space of known homotopies. ## pathfinder:=function(resolution, connectTo, sphereAndBounds, startingBit,startingbitboundary) local thingsThatCouldBeAdded, endpoint, newSphereAndBounds, addface, newstartingbitboundary, newstartingBit, returnpath; thingsThatCouldBeAdded:=Filtered(sphereAndBounds,i-> IntersectingUndirectedWords_LargeGroupRep(resolution,i[2],startingbitboundary) ); endpoint:=First(thingsThatCouldBeAdded,i-> IntersectingUndirectedWords_LargeGroupRep(resolution,i[2],connectTo) ); if endpoint<>fail then return UndirectedWord_LargeGroupRep(resolution,startingBit+endpoint[1]); else newSphereAndBounds:=Difference(sphereAndBounds,thingsThatCouldBeAdded); repeat if thingsThatCouldBeAdded=[] then return []; fi; addface:=Remove(thingsThatCouldBeAdded); newstartingbitboundary:=UndirectedWord_LargeGroupRep(resolution,startingbitboundary+addface[2]); newstartingBit:=UndirectedWord_LargeGroupRep(resolution,startingBit+addface[1]); returnpath:=pathfinder(resolution, connectTo, newSphereAndBounds, newstartingBit, newstartingbitboundary ); until returnpath<>[]; return UndirectedWord_LargeGroupRep(resolution,returnpath); fi; end; zero:=Zero(GroupRingOfResolution(resolution)); fam:=FamilyObj(zero); zerovec:=List([1..Size(area)],i->zero); sphereAndBounds:=[]; for term in [1..Size(area)] do if area[term]<>zero then groupels:=CoefficientsAndMagmaElementsAsLists(area[term])[2]; for g in groupels do letter:=ShallowCopy(zerovec); letter[term]:=ElementOfMagmaRing(fam,0,[1],[g]); Add(sphereAndBounds,[letter, UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,letter)] ); od; fi; od; if cell in cellblob then return List(cell,i->zero); fi; path:=pathfinder(resolution, UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,cell), sphereAndBounds, cell, UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,cell) ); if path=[] then return fail; else return path; fi; end); ############################################################################# ## ## given a word in the th term of , this returns true ## if and only if this word represents a contractible subspace. ## ## connectedness is not tested. ## Is this right, anyway? ## InstallMethod(IsContractibleWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,subspace) local chaincomplex, i; chaincomplex:=ChainComplexFromWordNC_LargeGroupRep(resolution,dim,subspace); return HomologyPb(chaincomplex,dim)=[]; end); ############################################################################# ## InstallMethod(IsContractibleWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,subspace) local converted_subspace; if IsFreeZGWord_LargeGroupRep(resolution,dim,subspace) then return IsContractibleWordNC_LargeGroupRep(resolution,dim,subspace); elif IsFreeZGWord(resolution,dim,subspace) then converted_subspace:=ConvertWordToStandardRep(resolution,dim,subspace); return IsContractibleWordNC_LargeGroupRep(resolution,dim,converted_subspace); else Error("invalid input"); fi; end); ############################################################################# ## ## InstallMethod(IsContractiblePartialSpace, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,spacelist) local spacelist_large; if ForAll([1..Size(spacelist)],subspace-> IsFreeZGWord_LargeGroupRep(resolution,subspace-1,spacelist[subspace])) then return IsContractiblePartialSpaceNC_LargeGroupRep(resolution,dim,spacelist); elif ForAll([1..Size(spacelist)],subspace-> IsFreeZGWord(resolution,subspace-1,spacelist[subspace])) then spacelist_large:=List(spacelist,space->ConvertStandardWord(resolution,dim,space)); return IsContractiblePartialSpaceNC_LargeGroupRep(resolution,dim,spacelist_large); else Error("subspacelist does not consist of valid words"); fi; end); ############################################################################# ## InstallMethod(IsContractiblePartialSpaceNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,spacelist) local chaincomplex; chaincomplex:=ChainComplexFromPartialSpaceNC_LargeGroupRep(resolution,spacelist{[1..dim+1]}); return Homology(chaincomplex,dim)=[]; end); ############################################################################# ## ## find the sphere that contains . ## The list of cells must induce a chain complex with th ## homology [0]. ## ############################################################################# ## ## check the input and delegate... ## InstallMethod(SphereContainingCell, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList], function(resolution,dim,space,cell) local complex; if not IsFreeZGLetter_LargeGroupRep(resolution,dim,cell) then Error(" is not a valid letter"); elif not IsFreeZGWord_LargeGroupRep(resolution,dim,space) then Error(" is not a valid word"); elif not IsUndirectedSubWord_LargeGroupRep(resolution,space,cell) then Error(" not in "); fi; complex:=ChainComplexFromWordNC_LargeGroupRep(resolution,dim,space); if not Homology(complex,dim)=[0] then Error(" does not contain a unique sphere"); fi; return SphereContainingCellNC_LargeGroupRep(resolution,dim,space,cell); end); ############################################################################# ## InstallMethod(SphereContainingCell_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList], function(resolution,dim,space,cell) local complex; if not IsFreeZGLetter_LargeGroupRep(resolution,dim,cell) then Error(" is not a valid letter"); elif not IsFreeZGWord_LargeGroupRep(resolution,dim,space) then Error(" is not a valid word"); elif not IsUndirectedSubWord_LargeGroupRep(resolution,space,cell) then Error(" not in "); fi; complex:=ChainComplexFromWordNC_LargeGroupRep(resolution,dim,space); if not Homology(complex,dim)=[0] then Error(" does not contain a unique sphere"); fi; return SphereContainingCellNC_LargeGroupRep(resolution,dim,space,cell); end); ############################################################################# ## ## InstallMethod(SphereContainingCellNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList,IsDenseList], function(resolution,dim,space,cell) local zero, fam, zerovec, space_and_bounds, term, groupels, g, letter, sphere, spherebound, sphere_done, subspacelist, complex, newcells, new_subspaces, i; zero:=Zero(GroupRingOfResolution(resolution)); fam:=FamilyObj(zero); zerovec:=List([1..Size(space)],i->zero); space_and_bounds:=[]; for term in [1..Size(space)] do if space[term]<>zero then groupels:=CoefficientsAndMagmaElementsAsLists(space[term])[2]; for g in groupels do letter:=ShallowCopy(zerovec); letter[term]:=ElementOfMagmaRing(fam,0,[1],[g]); Add(space_and_bounds,[letter, UndirectedBoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,dim,letter)] ); od; fi; od; Sort(space_and_bounds); sphere:=cell; sphere_done:=false; subspacelist:=SubspaceListFromWord_LargeGroupRep(resolution,dim,sphere); spherebound:=subspacelist[dim]; complex:=ChainComplexFromPartialSpaceNC_LargeGroupRep(resolution, subspacelist ); while Homology(complex,dim)<>[0] do newcells:=Filtered(space_and_bounds,c-> IntersectingUndirectedWordsNC_LargeGroupRep(resolution,c[2],spherebound) ); SubtractSet(space_and_bounds,newcells); sphere:=UndirectedWordNC_LargeGroupRep(resolution,sphere+Sum(List(newcells,i->i[1]))); new_subspaces:=SubspaceListFromWordNC_LargeGroupRep(resolution, dim, Sum(List(newcells,i->i[1])) ); for i in [1..Size(new_subspaces)] do subspacelist[i]:=UndirectedWordNC_LargeGroupRep(resolution,subspacelist[i]+new_subspaces[i]); od; spherebound:=subspacelist[dim]; complex:=ChainComplexFromPartialSpaceNC_LargeGroupRep(resolution,subspacelist); od; return sphere; end); ############################################################################# ## ## Generate a chain complex from a word ## InstallMethod(ChainComplexFromWord, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,subspace) local converted_subspace; if IsFreeZGWord_LargeGroupRep(resolution,dim,subspace) then return ChainComplexFromWordNC_LargeGroupRep(resolution,dim,subspace); elif IsFreeZGWord(resolution,dim,subspace) then converted_subspace:=ConvertStandardWord(resolution,dim,subspace); return ChainComplexFromWordNC_LargeGroupRep(resolution,dim,subspace); else Error("invalid input"); fi; end); InstallMethod(ChainComplexFromWordNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsInt,IsDenseList], function(resolution,dim,subspace) local spaces; spaces:=SubspaceListFromWordNC_LargeGroupRep(resolution,dim,subspace); return ChainComplexFromPartialSpaceNC_LargeGroupRep(resolution,spaces); end); ############################################################################# ## ## Generate a chain complex from a list of words ## InstallMethod(ChainComplexFromPartialSpace_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsDenseList], function(resolution,subspaces) if not ForAll([1..Size(subspaces)],dim-> IsFreeZGWord_LargeGroupRep(resolution,dim-1,subspaces[dim]) ) then Error("subspace list contains invalid words"); fi; return ChainComplexFromPartialSpaceNC_LargeGroupRep(resolution,subspaces); end); InstallMethod(ChainComplexFromPartialSpaceNC_LargeGroupRep, [IsHapLargeGroupResolutionRep,IsDenseList], function(resolution,subspaces) local word2vec, boundary, dimension, zero, zeroCoeff, oneCoeff, fam, generatorGroupEltsList, ccGenerators, term, thistermdimension, zerovec, dim, g, generator, complex, properties; ################################################## # /begin functions/ ## assuming that is a list of length ## where each entry is a list of group elements, ## we calculate the representation in the chain complex ## by just concatenating the coefficients. word2vec:=function(generators,word) local vec, term, coeffsAndGroupElts, termgenerators, g, pos; if Size(generators)<>Size(word) then Error("dimension mismatch"); fi; vec:=List(generators,i->0*[1..Size(i)]); for term in [1..Size(word)] do coeffsAndGroupElts:=CoefficientsAndMagmaElementsAsLists(word[term]); termgenerators:=generators[term]; for g in [1..Size(coeffsAndGroupElts[2])] do pos:=Position(termgenerators,coeffsAndGroupElts[2][g]); if pos<>fail then vec[term][pos]:=coeffsAndGroupElts[1][g]; else Error("word-vector conversion error"); fi; od; od; return Concatenation(vec); end; boundary:=function(k,j) local letter, boundaryAsWord; if k=Size(subspaces)+1 then return []; fi; boundaryAsWord:=BoundaryOfFreeZGLetterNC_LargeGroupRep(resolution,k,ccGenerators[k+1][j]); if boundaryAsWord=[] then return []; else return word2vec(generatorGroupEltsList[k],boundaryAsWord); fi; end; dimension:=function(k) if k List(s,i->Set(CoefficientsAndMagmaElementsAsLists(i)[2])) );; ccGenerators:=List(generatorGroupEltsList,i->[]); for term in [1..Size(generatorGroupEltsList)] do thistermdimension:=Size(generatorGroupEltsList[term]); zerovec:=List([1..thistermdimension],i->zero); for dim in [1..thistermdimension] do for g in [1..Size(generatorGroupEltsList[term][dim])] do generator:=ShallowCopy(zerovec); generator[dim]:=ElementOfMagmaRing(fam,zeroCoeff,[oneCoeff],[generatorGroupEltsList[term][dim][g]]); Add(ccGenerators[term],generator); od; od; od; complex:=Objectify(HapChainComplex, rec(dimension:=dimension, boundary:=boundary, subspaces:=List(subspaces), properties:= [["length", Size(subspaces)-1], ["characteristic", 0], ["type", "chainComplex"] ]) ); return complex; end); hapcryst-0.2.0/lib/translations.gd0000644000175100017510000000215015160525022016553 0ustar runnerrunner############################################################################# ## #W translations.gd HAPcryst package Marc Roeder ## ## ## ## #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 ## DeclareOperation("ShiftedOrbitPart", [IsVector,IsDenseList]); DeclareOperation("TranslationsToOneCubeAroundCenter",[IsVector,IsVector]); DeclareOperation("TranslationsToBox",[IsVector,IsDenseList]); hapcryst-0.2.0/lib/CWcomplexThings.gi0000644000175100017510000003521715160525022017127 0ustar runnerrunner############################################################################# ## #W CWcomplexThings.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## ## undirectedBoundary calculates just the cells occuring in the boundary. ## signs and multiplicities are ignored. ## InstallMethod(UndirectedBoundaryOfFreeZGLetter, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,cell) if not IsFreeZGLetter(resolution,dim,cell) then Error("invalid letter"); fi; return UndirectedBoundaryOfFreeZGLetterNC(resolution,dim,cell); end); InstallMethod(UndirectedBoundaryOfFreeZGLetterNC, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,cell) return Set(BoundaryOfFreeZGLetterNC(resolution,dim,cell),i->[AbsInt(i[1]),i[2]]); end); ############################################################################# ## ## undirectedBoundary for words ## InstallMethod(UndirectedBoundaryOfFreeZGWord, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) if not IsFreeZGWord(resolution,dim,word) then Error("invalid word"); fi; return UndirectedBoundaryOfFreeZGWordNC(resolution,dim,word); end); InstallMethod(UndirectedBoundaryOfFreeZGWordNC, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) return Union(List(word,cell->UndirectedBoundaryOfFreeZGLetterNC(resolution,dim,cell))); end); ############################################################################# ## ## InstallMethod(SubspaceListFromWord, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) if not IsFreeZGWord(resolution,dim,word) then Error(" is not a valid word"); fi; return SubspaceListFromWordNC(resolution,dim,word); end); InstallMethod(SubspaceListFromWordNC, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local subspaces, i; subspaces:=List([0..dim],i->[]); subspaces[dim+1]:=Set(word,i->[AbsInt(i[1]),i[2]]); for i in [dim-1,dim-2..0] do subspaces[i+1]:=Union(List(subspaces[i+2], j->UndirectedBoundaryOfFreeZGLetter(resolution,i+1,j)) ); od; return subspaces; end); ############################################################################# ## ## Tests if a word represents a connected supspace. ## InstallMethod(IsConnectedWord, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) if not IsFreeZGWord(resolution,dim,word) then Error(" is not a valid word"); fi; return IsConnectedWordNC(resolution,dim,word); end); InstallMethod(IsConnectedWordNC, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,word) local lettersAndBound, startblob, blobbound, addToBlob, addToBlobBound; lettersAndBound:=Set(word,letter-> [letter,UndirectedBoundaryOfFreeZGLetter(resolution,dim,letter)] ); # a "blob" is just that. A connected part of word. # We don't generate the blob. As we are just interesed in it's size. startblob:=Remove(lettersAndBound); blobbound:=startblob[2]; repeat addToBlob:=Filtered(lettersAndBound,i->Intersection(i[2],blobbound)<>[]); if addToBlob<>[] then SubtractSet(lettersAndBound,addToBlob); addToBlobBound:=Union(List(addToBlob,i->i[2])); blobbound:=Union(blobbound,addToBlobBound); fi; until lettersAndBound=[] or addToBlob=[]; if lettersAndBound=[] then return true; elif addToBlob=[] then return false; fi; end); ############################################################################# ## ## connect a cell to the subspace . ## InstallMethod(ConnectingPath, [IsHapResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList], function(resolution,dim,area,cellblob,cell) if not (IsFreeZGWord(resolution,dim,area) and IsFreeZGWord(resolution,dim,cellblob) ) then Error(" and must be valid words"); elif not IsFreeZGLetter(resolution,dim,cell) then Error(" is not a valid letter"); elif not IsSubset(area,cellblob) and cell in area then Error(" does not contain and "); fi; return ConnectingPathNC(resolution,dim,area,cellblob,cell); end); InstallMethod(ConnectingPathNC, [IsHapResolutionRep,IsInt,IsDenseList,IsDenseList,IsDenseList], function(resolution,dim,area,cellblob,cell) local pathfinder, sphereAndBounds, path; ################################################## ## ## The recursive function "pathfinder" assumes that connectTo is not empty. ## It calculates a path from a "disk" that connects a given starting part ## with the space of known homotopies. ## pathfinder:=function(resolution, connectTo, sphereAndBounds, startingBit,startingbitboundary) local thingsThatCouldBeAdded, endpoint, addface, newSphereAndBounds, newstartingbitboundary, newstartingBit, returnpath; thingsThatCouldBeAdded:=Filtered(sphereAndBounds,i->Intersection(i[2],startingbitboundary)<>[]); endpoint:=First(thingsThatCouldBeAdded,i->Intersection(i[2],connectTo)<>[]); if endpoint<>fail then return Concatenation(startingBit,[endpoint[1]]); else newSphereAndBounds:=Difference(sphereAndBounds,thingsThatCouldBeAdded); repeat if thingsThatCouldBeAdded=[] then return []; fi; addface:=Remove(thingsThatCouldBeAdded); newstartingbitboundary:=Union(startingbitboundary,addface[2]); newstartingBit:=Concatenation(startingBit,[addface[1]]); returnpath:=pathfinder(resolution, connectTo, newSphereAndBounds, newstartingBit, newstartingbitboundary ); until returnpath<>[]; return Unique(returnpath); fi; end; if cell in cellblob then return []; fi; sphereAndBounds:=Set(area,i->[i,UndirectedBoundaryOfFreeZGLetter(resolution,dim,i)]); path:=pathfinder(resolution, # undirectedReducedBoundaryOfWord(resolution,dim,cellblob), UndirectedBoundaryOfFreeZGLetter(resolution,dim,cell), sphereAndBounds, [cell], UndirectedBoundaryOfFreeZGLetter(resolution,dim,cell) ); if path=[] then return fail; else return path; fi; end); ############################################################################# ## ## given a word in the th term of , this returns true ## if and only if this word represents a contractible subspace. ## ## connectedness is not tested. ## Is this right, anyway? ## InstallMethod(IsContractibleWordNC, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,subspace) local chaincomplex, i; chaincomplex:=ChainComplexFromWordNC(resolution,dim,subspace); return Homology(chaincomplex,dim)=[]; end); InstallMethod(IsContractibleWord, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,subspace) if not IsFreeZGWord(resolution,dim,subspace) then Error("subspace is not a valid word"); fi; return IsContractibleWordNC(resolution,dim,subspace); end); ############################################################################# ## ## InstallMethod(IsContractiblePartialSpace, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,spacelist) if not ForAll(spacelist,subspace->IsFreeZGWord(resolution,dim,subspace)) then Error("subspace is not a valid word"); fi; return IsContractiblePartialSpaceNC(resolution,dim,spacelist); end); InstallMethod(IsContractiblePartialSpaceNC, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,spacelist) local chaincomplex; chaincomplex:=ChainComplexFromPartialSpaceNC(resolution,dim,spacelist); return Homology(chaincomplex,dim)=[]; end); ############################################################################# ## ## find the sphere that contains . ## The list of cells must induce a chain complex with th ## homology [0]. ## ############################################################################# ## ## check the input and delegate... ## InstallMethod(SphereContainingCell, [IsHapResolutionRep,IsInt,IsDenseList,IsDenseList], function(resolution,dim,space,cell) local complex; if not IsFreeZGLetter(resolution,dim,cell) then Error(" is not a valid letter"); elif not IsFreeZGWord(resolution,dim,space) then Error(" is not a valid word"); elif not cell in space then Error(" not in "); fi; complex:=ChainComplexFromPartialSpace(resolution,dim,space); if not Homology(complex,dim)=[0] then Error(" does not contain a unique sphere"); fi; return SphereContainingCellNC(resolution,dim,space,cell); end); ############################################################################# ## ## InstallMethod(SphereContainingCellNC, [IsHapResolutionRep,IsInt,IsDenseList,IsDenseList], function(resolution,dim,space,cell) local space_and_bounds, sphere, spherebound, sphere_done, subspacelist, complex, newcells, new_subspaces, i; space_and_bounds:=List(space,i->[i,UndirectedBoundaryOfFreeZGWord(resolution,dim,i)]); sphere:=[cell]; spherebound:=UndirectedBoundaryOfFreeZGWord(resolution,dim,sphere); sphere_done:=false; subspacelist:=SubspaceListFromWord(resolution,dim,sphere); complex:=ChainComplexFromPartialSpace(resolution, dim, subspacelist ); while not Homology(complex,dim)=[0] do newcells:=Filtered(space_and_bounds,c->ForAny(c[2],i->i in spherebound)); SubtractSet(space_and_bounds,newcells); UniteSet(sphere,List(newcells,i->i[1])); UniteSet(spherebound,Concatenation(List(newcells,i->i[2]))); new_subspaces:=SubspaceListFromWord(resolution, dim, List(newcells,i->i[1]) ); for i in [1..Size(new_subspaces)] do UniteSet(subspacelist[i],new_subspaces[i]); od; od; return Set(sphere); end); ############################################################################# ## ## Generate a chain complex from a word ## InstallMethod(ChainComplexFromWord, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,subspace) if not IsFreeZGWord(resolution,dim,subspace) then Error(" is not a proper word"); fi; return ChainComplexFromWordNC(resolution,dim,subspace); end); InstallMethod(ChainComplexFromWordNC, [IsHapResolutionRep,IsInt,IsDenseList], function(resolution,dim,subspace) local spaces; spaces:=SubspaceListFromWord(resolution,dim,subspace); return ChainComplexFromPartialSpaceNC(resolution,spaces); end); ############################################################################# ## ## Generate a chain complex from a list of words ## InstallMethod(ChainComplexFromPartialSpace, [IsHapResolutionRep,IsDenseList], function(resolution,subspaces) if not ForAll([1..Size(subspaces)],dim-> IsFreeZGWord(resolution,dim-1,subspaces[dim]) ) then Error("subspace list contains invalid words"); fi; return ChainComplexFromPartialSpaceNC(resolution,subspaces); end); ############################################################################# ## InstallMethod(ChainComplexFromPartialSpaceNC, [IsHapResolutionRep,IsDenseList], function(resolution,subspaces) local undirectedLetter, word2vec, boundary, dimension, complex, properties; undirectedLetter:=function(letter) return [AbsInt(letter[1]),letter[2]]; end; word2vec:=function(generators,word) local vec, letter, pos; vec:=List([1..Size(generators)],i->0); for letter in word do pos:=Position(generators,undirectedLetter(letter)); if pos<>fail then vec[pos]:=vec[pos]+SignInt(letter[1]); else Error("word-vector conversion error"); fi; od; return vec; end; boundary:=function(k,j) local letter, boundaryAsWord; if k=Size(subspaces+1) then return []; fi; letter:=subspaces[k+1][j]; boundaryAsWord:=BoundaryOfFreeZGLetterNC(resolution,k,letter); return word2vec(subspaces[k],boundaryAsWord); end; dimension:=function(k) if k find the edge of the cube
+{-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) and an offset vector as well as the part of # the orbit around
, the interesting inequalities induced by # +offset are calculated, assuming that only points nearer # than 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) then # if ForAny(vertices,thiscorner->WhichSideOfHyperplane(thiscorner,ineq)=-1) 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 [] 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 currentsum1 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.maxsumIsSubset(f,face))) then Unbind(faces[faceindex]); fi; od; end; orbitDecompositionAsIndices:=function(facelist,vertexlist,group) local sortedvertices, sortperm, vertexpositionlookup, todolist, setfacelist, returnlist, thissize, list, orbit, thisorbit, fpos, fpositions; if not ForAll(facelist,IsSet) then Error("face list must be a list of sets"); fi; sortedvertices:=ShallowCopy(vertexlist); sortperm:=Sortex(sortedvertices); vertexpositionlookup:=Permuted([1..Size(sortedvertices)],sortperm); # convert all faces to vectors: todolist:=Set(facelist,i->Set(vertexlist{i})); if IsSet(facelist) then setfacelist:=facelist; else setfacelist:=AsSet(facelist); fi; returnlist:=[]; while todolist<>[] do thissize:=Size(todolist[1]); list:=Filtered(todolist,o->Size(o)=thissize); SubtractSet(todolist,list); while list<>[] do orbit:=OrbitPartAndRepresentativesInFacesStandardSpaceGroup(group,list[1],list); thisorbit:=[]; for fpos in [1..Size(orbit)] do fpositions:=Set(orbit[fpos][1],i->vertexpositionlookup[PositionSet(sortedvertices,i)]); if fpositions in setfacelist then Add(thisorbit,[Position(facelist,fpositions),orbit[fpos][2]]); fi; od; Add(returnlist,thisorbit); SubtractSet(list,List(orbit,i->i[1])); od; od; return returnlist; end; changeHasseEntries:=function(orbitsandreps,codim,vertices,hasse,group) local genIndices, faces, nrupfaces, upfaces, newhasseentry, idMat, orbit, gen, genIndex, upindices, upface, genvertices, o, oface, entry; genIndices:=[]; faces:=hasse[codim+1]; nrupfaces:=Size(hasse[codim]); upfaces:=hasse[codim]{[1..nrupfaces]}[1]; newhasseentry:=[]; idMat:=IdentityMat(Size(hasse)); for orbit in orbitsandreps do gen:=faces[orbit[1][1]]; Add(newhasseentry,[gen,[]]); genIndex:=Size(newhasseentry); upindices:=Filtered([1..nrupfaces], i->IsSubset(upfaces[i],gen)); #update boundary for faces containing new generator: for upface in upindices do AddSet(hasse[codim][upface][2],[genIndex,idMat]); od; #replace all faces in the generator-orbit with representatives: if Size(orbit)>1 then genvertices:=Set(vertices{gen}); for o in orbit{[2..Size(orbit)]} do oface:=faces[o[1]]; upindices:=Filtered([1..nrupfaces], i->IsSubset(upfaces[i],oface)); entry:=[genIndex,o[2]]; for upface in upindices do AddSet(hasse[codim][upface][2],entry); od; od; fi; od; return newhasseentry; end; #this replaces the matrices in the partial Hasse diagram with integers and # returns a list of matrices. This is done to comply with the structure # of a resolution in HAP. reformatHD:=function(hasse) local elts, faces, face, line; elts:=[]; for faces in hasse do for face in faces do for line in face[2] do Add(elts,line[2]); od; od; od; # if elts<>[] then # elts:=Set(elts); # AddSet(elts,IdentityMat(Size(elts[1]))); # for faces in hasse do # for face in faces do # for line in face[2] do # if not IsInt(line[2]) then # line[2]:=PositionSet(elts,line[2]); # fi; # od; # od; # od; # fi; return elts; end; ## This does not generate group ring elements. The group ring is ## generated in the resolution generator. So here, we only generate ## the coefficient-group element pairs. reformatHD_GroupRing:=function(groupring,hasse) local zero, family, groupelements, dim, face, term, firstpos, firstgen, position, firspos, one, onepos; zero:=Zero(groupring); family:=FamilyObj(zero); groupelements:=[]; for dim in [2..Size(hasse)] do for face in hasse[dim] do for term in face[2] do if IsMatrix(term[2]) then Add(groupelements,term[2]); term[2]:=SignInt(term[1])* ElementOfMagmaRing(family,0,[1],[term[2]]); term[1]:=AbsInt(term[1]); fi; od; Sort(face[2]); firstpos:=1; firstgen:=face[2][firstpos][1]; for position in [2..Size(face[2])] do if face[2][position][1]=firstgen then face[2][firstpos][2]:=face[2][firstpos][2] +face[2][position][2]; Unbind(face[2][position]); else firstpos:=position; firstgen:=face[2][position][1]; fi; od; face[2]:=Compacted(face[2]); # face[2]:=vector; od; od; groupelements:=Set(groupelements); one:=One(UnderlyingMagma(groupring)); if groupelements[1]<>one then onepos:=Position(groupelements,one); groupelements[onepos]:=groupelements[1]; groupelements[1]:=one; fi; return groupelements; end; ###################################################################### ###################################################################### ################################################## ## THIS IS JUST FOR BIEBERBACH GROUPS! ## ## here, hasse has to be a list contining the generators of ## dimension $k$ in the $k+1$st entry. ## each of the genertors already knows it's unoriented boundary. ## ## Signs are now assigned to the boundary to define a proper ## boundary homomorphism. ## calculateBoundary:=function(k,j,hasse) local dirLess, boundaryFromPair, face, facebound, linesdone, linestodo, linesinpoint, pointset, idMat, line, linemat, points, point, pos, firstlinepos, firstline, linesforthisrun, nextlines, pointsdone, linebound, lineboundDirless, dirlessline, pointsign, otherline, otherlinepos, otherlinebound, orientedOtherLine; dirLess:=function(face) return [AbsInt(face[1]),face[2]]; end; boundaryFromPair:=function(dim,pair,hasse) local gen, bound; gen:=hasse[dim+1][AbsInt(pair[1])]; bound:=gen[2]; return List(bound,b->[SignInt(pair[1])*b[1],b[2]*pair[2]]); end; face:=hasse[k+1][j]; ################################ ## face is of the form ## [ , ] ## where ## is a list of integers enumerating the vertices of the ## fundamental domain ## ## is a list of pairs [,] ## with an integer denoting the position of a face ## in the list hasse[k]. is an affine matrix taking the ## ## hasse[k][downfaceindex] to the desired face. ## ## ## ## ########################### if k=1 then # First, define the boundary of 1-faces facebound:=face[2]; if facebound[1]>facebound[2] then linesdone:=[facebound[1],[-facebound[2][1],facebound[2][2]]]; else linesdone:=[[-facebound[1][1],facebound[1][2]],facebound[2]]; fi; else # #now the other faces. Note that in an n-face every # n-2 face is contained in exactly 2 n-1 faces. ############################## linestodo:=Set(face[2],i->dirLess(i)); # # the edges which are generators for this module: # GenLinesTodo:=Filtered(linestodo,i->i[2]=idMat); # # edges which are images under generators for this module: # ImLinesTodo:=Filtered(linestodo,i->i[2]<>idMat); # As the group is Bieberbach, each point has a unique name. # generate a list to look up the incident lines for each point: linesinpoint:=[]; pointset:=[]; idMat:=IdentityMat(Size(hasse)); for line in linestodo do # form: line=[,] # : generator position # : matrix taking generator to actual line. linemat:=line[2]; points:=List(hasse[k][line[1]][2],p->[AbsInt(p[1]),p[2]*linemat]); for point in points do #form of point as form of line but one dimension lower if not point in pointset then Add(linesinpoint,[point,[line]]); else pos:=PositionSet(pointset,point); AddSet(linesinpoint[pos][2],line); fi; od; UniteSet(pointset,points); Sort(linesinpoint); od; firstlinepos:=PositionProperty(linestodo,i->i[2]=idMat); if firstlinepos=fail then firstline:=Remove(linestodo); else firstline:=linestodo[firstlinepos]; Remove(linestodo,firstlinepos); fi; linesforthisrun:=[firstline]; nextlines:=[]; pointsdone:=[]; linesdone:=[]; repeat for line in linesforthisrun do linesdone:=Set(linesdone); if not ([line[1],line[2]] in linesdone or [-line[1],line[2]] in linesdone) then Add(linesdone,line); fi; linebound:=boundaryFromPair(k-1,line,hasse); lineboundDirless:=List(linebound,dirLess); SortParallel(lineboundDirless,linebound); dirlessline:=dirLess(line); points:=Difference(lineboundDirless,pointsdone); for point in points do Add(pointsdone,point); pointsign:=SignInt(linebound[PositionSet(lineboundDirless,point)][1]); otherline:=linesinpoint[PositionSet(pointset,point)]; otherline:=First(otherline[2],l->l<>dirlessline); if otherline in linestodo then RemoveSet(linestodo,otherline); otherlinebound:=boundaryFromPair(k-1,otherline,hasse); if pointsign=SignInt(First(otherlinebound,i->dirLess(i)=point)[1]) then orientedOtherLine:=[-otherline[1],otherline[2]]; else orientedOtherLine:=otherline; fi; Add(linesdone,orientedOtherLine); Add(nextlines,orientedOtherLine); fi; od; od; linesforthisrun:=ShallowCopy(nextlines); nextlines:=[]; until linesforthisrun=[]; fi; ## return new boundary entry: return Set(linesdone); end; ###################################################################### ###################################################################### if not IsStandardSpaceGroup(group) and IsAffineCrystGroupOnRight(group) then Error(" must be a StandardSpaceGroup acting on right"); fi; dim:=DimensionOfMatrixGroup(group)-1; starttime:=Runtime(); Polymake(poly,"VERTICES"); vertices:=Polymake(poly,"VERTICES"); MakeImmutable(vertices); if not dim=Size(vertices[1]-1) then Error("group and polyhedron do not match"); fi; ## # Add initial (top) node: # Note that the face lattice is generated top- down. So the # order has to be reversed to be ascending in dimension. ## hasse:=Concatenation([[[[1..Size(vertices)],[]]]], #StructuralCopy(Polymake(poly,"FACE_LATTICE"){[1..dim]})); StructuralCopy(PolymakeFaceLattice(poly){[1..dim]})); #moduleGenerators:=List([1..dim+1],i->[]); #moduleGenerators is a list of list. The i^{th} entry contains the # positions of the module generators of dimension i in the Hasse diagram. # moduleGenerators[1]:=[1];# so this means [hasse[1][1]]; #Now the next nodes: for codim in [1..dim] do #At this stage, hasse[codim+1] is a list of faces. initialfacenumber:=Size(hasse[codim+1]);########## timetmp:=Runtime();######## removeSomeFaces(List(hasse[codim],i->i[1]),hasse[codim+1]); hasse[codim+1]:=Set(hasse[codim+1]); faceOrbits:=orbitDecompositionAsIndices(hasse[codim+1],vertices,group); hasse[codim+1]:=changeHasseEntries(faceOrbits,codim,vertices,hasse,group); Info(InfoHAPcryst,3,codim,"(",Size(hasse[codim+1]),"/",initialfacenumber,"):",StringTime(Runtime()-timetmp)); od; for codim in [1..Int((dim+1)/2)] do tmp:=hasse[codim]; hasse[codim]:=hasse[dim+2-codim]; hasse[dim+2-codim]:=tmp; od; Info(InfoHAPcryst,3,"Face lattice done (",StringTime(Runtime()-starttime),"). Calculating boundary "); for k in [1..dim] do for j in [1..Size(hasse[k+1])] do hasse[k+1][j][2]:=calculateBoundary(k,j,hasse); od; od; if fail in Flat(hasse) then Error("boundary generation failed"); fi; Info(InfoHAPcryst,3,"done (",StringTime(Runtime()-timetmp),") Reformating...\c"); # elts:=reformatHD(hasse); groupring:=GroupRing(Integers,group); elts:=reformatHD_GroupRing(groupring,hasse); # elts:=[IdentityMat(dim+1)]; return rec(hasse:=hasse,elts:=elts,groupring:=groupring); end); hapcryst-0.2.0/lib/FundamentalDomainBieberbach.gi0000644000175100017510000002752415160525022021370 0ustar runnerrunner############################################################################# ## #W FundamentalDomainBieberbach.gi HAPcryst package Marc Roeder ## ## ## ## #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 ## ############################################################################# ## #O FundamentalDomainBieberbachGroupNC() ## InstallMethod(FundamentalDomainBieberbachGroupNC, [IsGroup], function(group) local center; center:=0*[1..Size(Representative(group))-1]; return FundamentalDomainBieberbachGroupNC(center,group); end); ############################################################################# ## #O FundamentalDomainBieberbachGroup() ## InstallMethod(FundamentalDomainBieberbachGroup, [IsGroup], function(group) local center; center:=0*[1..Size(Representative(group))-1]; return FundamentalDomainBieberbachGroup(center,group); end); ############################################################################# ## #O FundamentalDomainBieberbachGroupNC(
, ) ## InstallMethod(FundamentalDomainBieberbachGroupNC, [IsVector,IsGroup], function(center,group) local gram; gram:=GramianOfAverageScalarProductFromFiniteMatrixGroup(PointGroup(group)); return FundamentalDomainBieberbachGroupNC(center,group,gram); end); ############################################################################# ## #O FundamentalDomainBieberbachGroup(
, ) ## InstallMethod(FundamentalDomainBieberbachGroup, [IsVector,IsGroup], function(center,group) local gram; gram:=GramianOfAverageScalarProductFromFiniteMatrixGroup(PointGroup(group)); return FundamentalDomainBieberbachGroup(center,group,gram); end); ############################################################################# ## #O FundamentalDomainBieberbachGroup(
, , ) ## InstallMethod(FundamentalDomainBieberbachGroup, [IsVector,IsGroup,IsMatrix], function(center,group,gram) local needBieberbachTest, phi, dim, fd; needBieberbachTest:=false; if not (IsStandardSpaceGroup(group) and IsAffineCrystGroupOnRight(group)) then Error("group must be a StandardSpaceGroup acting on right"); else phi:=IsomorphismPcpGroup(group); if phi=fail then Info(InfoHAPcryst,1,"Couldn't calculate pcp representation. Testing tortion freeness later"); needBieberbachTest:=true; elif not IsAlmostBieberbachGroup(Image(phi)) then Error("group must be a Bieberbach group"); fi; fi; dim:=Size(center); if not (dim=Size(gram) and DimensionOfMatrixGroup(group)=dim+1) then Error("dimensions don't match"); fi; if not IsTrivial(StabilizerOnSetsStandardSpaceGroup(group,[center])) then Error("group must be a Bieberbach group"); fi; fd:=FundamentalDomainBieberbachGroupNC(center,group,gram); if not needBieberbachTest or IsFundamentalDomainBieberbachGroup(fd,group) then return fd; else Error("group must be a Bieberbach group"); fi; end); ############################################################################# ## #O FundamentalDomainBieberbachGroupNC(
, , ) ## InstallMethod(FundamentalDomainBieberbachGroupNC, [IsVector,IsGroup,IsMatrix], function(center,group,gram) local initialInequalities, satisfiesAllInequalities, newInequalitiesEuclidean, newInequalities, shuffledList, dim, fdVol, ineqThreshold, isEuclidean, orbitpart, partialFD, newinequalities, oldinequalities, donevertices, allvertices, vertices, box, i, ilist, inequalities, v, new; ################### ## A lot of helper functions: ################### # This calculates the inequalities for the unit box around initialInequalities:=function(center,gram) local dim, directions, points, ineqs; dim:=Size(center); directions:=Union(IdentityMat(dim),-IdentityMat(dim)); points:=[]; points:=center+directions; #points:=Set(ShiftedOrbitPart(center,orbitpart)); #UniteSet(points,center+directions); # UniteSet(points,Union(List(directions,d->d+points))); if gram<>IdentityMat(dim) then ineqs:=Set(points, i->BisectorInequalityFromPointPair(center,i,gram)); else ineqs:=Set(points, i->BisectorInequalityFromPointPair(center,i)); fi; RemoveSet(ineqs,fail); return ineqs; end; satisfiesAllInequalities:=function(point,ineqs) return ForAll(ineqs,i->WhichSideOfHyperplaneNC(point,i) in [0,1]); end; newInequalitiesEuclidean:=function(vertex,center,ineqs,vertices,box,group) local dim, affinevertex, returnlist, g, affimage, image, trans, t, gl, gli, gt; dim:=Size(vertex); affinevertex:=Concatenation(vertex,[1]); returnlist:=[]; for g in PointGroupRepresentatives(group) do gl:=LinearPartOfAffineMatOnRight(g); gli:=Inverse(gl); gt:=g[dim+1]{[1..dim]}; affimage:=affinevertex*g; image:=affimage{[1..dim]}; ### trans:=TranslationsToBox(image,box); for t in trans do if not image+t in vertices then if satisfiesAllInequalities(image+t,ineqs) then Add(returnlist,center*gl+gt+t); Add(returnlist,(center-gt-t)*gli); fi; fi; od; od; if returnlist=[] then return []; fi; returnlist:=Set(returnlist); RemoveSet(returnlist,center); returnlist:=Set(returnlist,i->BisectorInequalityFromPointPair(center,i)); SubtractSet(returnlist,ineqs); return Filtered(returnlist,i->ForAny(vertices,v->WhichSideOfHyperplaneNC(v,i)=-1)); end; newInequalities:=function(vertex,center,ineqs,vertices,box,group,gram) local dim, affinevertex, returnlist, g, gl, gli, gt, affimage, image, trans, t; dim:=Size(vertex); affinevertex:=Concatenation(vertex,[1]); returnlist:=[]; for g in PointGroupRepresentatives(group) do gl:=LinearPartOfAffineMatOnRight(g); gli:=Inverse(gl); gt:=g[dim+1]{[1..dim]}; affimage:=affinevertex*g; image:=affimage{[1..dim]}; ### trans:=TranslationsToBox(image,box); for t in trans do if not image+t in vertices then if satisfiesAllInequalities(image+t,ineqs) then Add(returnlist,center*gl+gt+t); Add(returnlist,(center-gt-t)*gli); fi; fi; od; od; if returnlist=[] then return []; fi; returnlist:=Set(returnlist); RemoveSet(returnlist,center); returnlist:=Set(returnlist,i->BisectorInequalityFromPointPair(center,i,gram)); SubtractSet(returnlist,ineqs); return Filtered(returnlist,i->ForAny(vertices,v->WhichSideOfHyperplaneNC(v,i)=-1)); end; shuffledList:=function(list) local positionlist, indexlist, i, nextpos; if Size(list)=1 then return list; fi; positionlist:=EmptyPlist(Size(list)); indexlist:=[1..Size(list)]; for i in [Size(list),Size(list)-1..1] do nextpos:=Random(1,i); Add(positionlist,indexlist[nextpos]); Remove(indexlist,nextpos); od; return list{positionlist}; end; ################### ## helper functions done. Let's go: ################### dim:=Size(center); ## The volume of a fundamental domain is seemingly ## well-known: #fdVol:=1/Order(PointGroup(group)); ## This is only used in the first step. ## Polymake calculates a triangulation using the beneath-beyond ## algorithm for this. ## This seams to be inefficient in high dimensions, especially ## with complicated polyhedrae. ## ineqThreshold:=ValueOption("ineqThreshold"); if ineqThreshold=fail then ineqThreshold:=200; fi; isEuclidean:=(gram=IdentityMat(dim)); orbitpart:=OrbitStabilizerInUnitCubeOnRight(group,center).orbit;; newinequalities:=initialInequalities(center,gram);; partialFD:=CreatePolymakeObject("partialFD", POLYMAKE_DATA_DIR, ["polytope","2.3","RationalPolytope"] ); AppendToPolymakeObject(partialFD, ConvertMatrixToPolymakeString("FACETS",newinequalities) ); # AppendInequalitiesToPolymakeObject(partialFD,newinequalities); ## slightly experimental: remove if this causes trouble: Polymake(partialFD,"VERTICES FACETS"); newinequalities:=[]; oldinequalities:=[]; donevertices:=[]; allvertices:=[]; repeat allvertices:=AsSet(Polymake(partialFD,"VERTICES")); donevertices:=Set(donevertices); vertices:=Difference(allvertices,donevertices); ## box:=[1..dim]; for i in [1..dim] do ilist:=allvertices{[1..Size(allvertices)]}[i]; box[i]:=[Minimum(ilist),Maximum(ilist)]; od; # Sort(donevertices); # vertices:=(Filtered(Polymake(partialFD,"VERTICES"),v->not v in donevertices)); # vertices:=Difference(allvertices,donevertices); if vertices=[] then Info(InfoHAPcryst,2,"out of vertices"); return partialFD; fi; inequalities:=Set(Polymake(partialFD,"FACETS")); Info(InfoHAPcryst,3,"v: ",Size(allvertices),"/",Size(vertices)," f:", Size(inequalities)," \c"); newinequalities:=[]; repeat v:=Remove(vertices,Random(1,Size(vertices))); # v:=Remove(vertices); Add(donevertices,v); if satisfiesAllInequalities(v,newinequalities) then if isEuclidean then new:= newInequalitiesEuclidean(v,center,inequalities, allvertices,box,group); else new:= newInequalities(v,center,inequalities, allvertices,box,group,gram); fi; UniteSet(inequalities,new); Append(newinequalities,new); fi; until vertices=[] or Size(newinequalities)>ineqThreshold; Info(InfoHAPcryst,3,"new: ",Size(newinequalities)); if newinequalities<>[] then ClearPolymakeObject(partialFD,["polytope","2.3","RationalPolytope"]); # AppendInequalitiesToPolymakeObject(partialFD,shuffledList(inequalities));; AppendInequalitiesToPolymakeObject(partialFD,inequalities);; Polymake(partialFD,"VERTICES FACETS"); fi; until newinequalities=[]; Info(InfoHAPcryst,2,"out of inequalities"); return partialFD; end); hapcryst-0.2.0/tst/0000755000175100017510000000000015160525022013564 5ustar runnerrunnerhapcryst-0.2.0/tst/bugfix.tst0000644000175100017510000000205315160525022015604 0ustar runnerrunnergap> START_TEST("Test for various former bugs"); # # IsSquareMat used to return 'true' for all matrices # gap> IsSquareMat([[1]]); true gap> IsSquareMat([[1, 2]]); false # # DimensionSquareMat # gap> DimensionSquareMat([[1,2,3],[1,2,3],[1,2,3]]); 3 gap> DimensionSquareMat([[1,2,3],[1,2,3]]); fail gap> DimensionSquareMat([[1,2],[1,2,3]]); fail # # Let TranslationsToBox return a list again, instead of an iterator. # See # gap> TranslationsToBox([0,0],[[1/2,2/3],[1/2,2/3]]); [ ] gap> TranslationsToBox([0,0],[[-3/2,1/2],[1,4/3]]); [ [ -1, 1 ], [ 0, 1 ] ] gap> TranslationsToBox([0,0],[[-3/2,1/2],[2,1]]); Error, Box must not be empty # gap> S:=SpaceGroup(3,5);; gap> p:=[4/3,5/3,7/3];; gap> o:=OrbitStabilizerInUnitCubeOnRight(S,VectorModOne(p)).orbit; [ [ 1/3, 2/3, 1/3 ], [ 1/3, 2/3, 2/3 ] ] gap> box:=p+[[-1,1],[-1,1],[-1,1]]; [ [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ] ] gap> o2:=Concatenation(List(o,i->i+TranslationsToBox(i,box)));; gap> Size(o2); 54 # gap> STOP_TEST( "bugfix.tst" ); hapcryst-0.2.0/tst/HAPcryst.tst0000644000175100017510000000552615160525022016025 0ustar runnerrunnergap> START_TEST("HAPcryst test"); gap> G:=SpaceGroup(3,165); SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) gap> SetInfoLevel(InfoHAPcryst,1); gap> PointGroupRepresentatives(G); [ [ [ -1, -1, 0, 0 ], [ 1, 0, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 5/3, 1 ] ], [ [ -1, 0, 0, 0 ], [ 0, -1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 1/2, 1 ] ], [ [ 0, -1, 0, 0 ], [ 1, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 5/6, 1 ] ], [ [ 0, 1, 0, 0 ], [ -1, -1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 4/3, 1 ] ], [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 1, 1, 0, 0 ], [ -1, 0, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 13/6, 1 ] ] ] gap> res:=ResolutionBieberbachGroup(G); Resolution of length 4 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) . No contracting homotopy available. # gap> List([0..3],Dimension(res)); [ 2, 5, 4, 1 ] gap> BoundaryOfGenerator_LargeGroupRep(res,2,1); [ (1)*[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], (-1)*[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], (-1)*[ [ 1, 1, 0, 0 ], [ -1, 0, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 1/6, 1 ] ], of ..., (1)*[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ] gap> res:=ResolutionBieberbachGroup(G,[1/2,1/3,1/5]); Resolution of length 4 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) . No contracting homotopy available. # gap> List([0..3],Dimension(res)); [ 9, 18, 10, 1 ] gap> BoundaryOfGenerator_LargeGroupRep(res,2,1); [ (1)*[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], (-1)*[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ]+( -1)*[ [ 1, 1, 0, 0 ], [ -1, 0, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 1/6, 1 ] ], (1)*[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], (-1)*[ [ -1, 0, 0, 0 ], [ 0, -1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 1/2, 1 ] ], of ..., (1)*[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], (-1)*[ [ -1, -1, 0, 0 ], [ 1, 0, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 2/3, 1 ] ], of ..., (-1)*[ [ 1, 1, 0, 0 ], [ -1, 0, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 1/6, 1 ] ], of ..., of ..., (1)*[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], of ..., (-1)*[ [ 1, 1, 0, 0 ], [ -1, 0, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 1/6, 1 ] ], of ..., of ..., (1)*[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], of ... ] gap> res:=ResolutionBieberbachGroup(SpaceGroup(4,4)); Resolution of length 5 in characteristic 0 for SpaceGroupOnRightBBNWZ( 4, 2, 1, 1, 2 ) . No contracting homotopy available. # gap> List([0..4],i->Homology(TensorWithIntegers(res),i)); [ [ 0 ], [ 2, 0, 0, 0 ], [ 2, 2, 0, 0, 0 ], [ 2, 0 ], [ ] ] gap> List([0..4],i->Cohomology(HomToIntegers(res),i)); [ [ 0 ], [ 0, 0, 0 ], [ 2, 0, 0, 0 ], [ 2, 2, 0 ], [ 2 ] ] # gap> STOP_TEST("tst.g", 10000); hapcryst-0.2.0/tst/testall.g0000644000175100017510000000031215160525022015400 0ustar runnerrunnerLoadPackage("hapcryst"); TestDirectory(DirectoriesPackageLibrary( "hapcryst", "tst" ), rec(exitGAP := true, testOptions := rec(compareFunction := "uptowhitespace") ) ); FORCE_QUIT_GAP(1); hapcryst-0.2.0/LICENSE0000644000175100017510000004310315160525022013760 0ustar runnerrunner GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. hapcryst-0.2.0/makedoc.g0000644000175100017510000000047715160525022014535 0ustar runnerrunner## this creates the documentation, needs: GAPDoc and AutoDoc packages, pdflatex ## ## Call this with GAP from within the package directory. ## if fail = LoadPackage("AutoDoc", ">= 2016.01.21") then Error("AutoDoc 2016.01.21 or newer is required"); fi; AutoDoc(rec( scaffold := rec( MainPage := false ), )); hapcryst-0.2.0/doc/0000755000175100017510000000000015160525022013517 5ustar runnerrunnerhapcryst-0.2.0/doc/HAPcryst.tex0000644000175100017510000030622115160525022015742 0ustar runnerrunner% generated by GAPDoc2LaTeX from XML source (Frank Luebeck) \documentclass[a4paper,11pt]{report} \usepackage[top=37mm,bottom=37mm,left=27mm,right=27mm]{geometry} \sloppy \pagestyle{myheadings} \usepackage{amssymb} \usepackage[utf8]{inputenc} \usepackage{makeidx} \makeindex \usepackage{color} \definecolor{FireBrick}{rgb}{0.5812,0.0074,0.0083} \definecolor{RoyalBlue}{rgb}{0.0236,0.0894,0.6179} \definecolor{RoyalGreen}{rgb}{0.0236,0.6179,0.0894} \definecolor{RoyalRed}{rgb}{0.6179,0.0236,0.0894} \definecolor{LightBlue}{rgb}{0.8544,0.9511,1.0000} \definecolor{Black}{rgb}{0.0,0.0,0.0} \definecolor{linkColor}{rgb}{0.0,0.0,0.554} \definecolor{citeColor}{rgb}{0.0,0.0,0.554} \definecolor{fileColor}{rgb}{0.0,0.0,0.554} \definecolor{urlColor}{rgb}{0.0,0.0,0.554} \definecolor{promptColor}{rgb}{0.0,0.0,0.589} \definecolor{brkpromptColor}{rgb}{0.589,0.0,0.0} \definecolor{gapinputColor}{rgb}{0.589,0.0,0.0} \definecolor{gapoutputColor}{rgb}{0.0,0.0,0.0} %% for a long time these were red and blue by default, %% now black, but keep variables to overwrite \definecolor{FuncColor}{rgb}{0.0,0.0,0.0} %% strange name because of pdflatex bug: \definecolor{Chapter }{rgb}{0.0,0.0,0.0} \definecolor{DarkOlive}{rgb}{0.1047,0.2412,0.0064} \usepackage{fancyvrb} \usepackage{mathptmx,helvet} \usepackage[T1]{fontenc} \usepackage{textcomp} \usepackage[ pdftex=true, bookmarks=true, a4paper=true, pdftitle={Written with GAPDoc}, pdfcreator={LaTeX with hyperref package / GAPDoc}, colorlinks=true, backref=page, breaklinks=true, linkcolor=linkColor, citecolor=citeColor, filecolor=fileColor, urlcolor=urlColor, pdfpagemode={UseNone}, ]{hyperref} \newcommand{\maintitlesize}{\fontsize{50}{55}\selectfont} % write page numbers to a .pnr log file for online help \newwrite\pagenrlog \immediate\openout\pagenrlog =\jobname.pnr \immediate\write\pagenrlog{PAGENRS := [} \newcommand{\logpage}[1]{\protect\write\pagenrlog{#1, \thepage,}} %% were never documented, give conflicts with some additional packages \newcommand{\GAP}{\textsf{GAP}} %% nicer description environments, allows long labels \usepackage{enumitem} \setdescription{style=nextline} %% depth of toc \setcounter{tocdepth}{1} %% command for ColorPrompt style examples \newcommand{\gapprompt}[1]{\color{promptColor}{\bfseries #1}} \newcommand{\gapbrkprompt}[1]{\color{brkpromptColor}{\bfseries #1}} \newcommand{\gapinput}[1]{\color{gapinputColor}{#1}} \begin{document} \logpage{[ 0, 0, 0 ]} \begin{titlepage} \mbox{}\vfill \begin{center}{\maintitlesize \textbf{ HAPcryst \mbox{}}}\\ \vfill \hypersetup{pdftitle= HAPcryst } \markright{\scriptsize \mbox{}\hfill HAPcryst \hfill\mbox{}} {\Huge \textbf{ A HAP extension for crystallographic groups \mbox{}}}\\ \vfill {\Huge Version 0.2.0 \mbox{}}\\[1cm] { 24 March 2026 \mbox{}}\\[1cm] \mbox{}\\[2cm] {\Large \textbf{ Marc Roeder\\ \mbox{}}}\\ \hypersetup{pdfauthor= Marc Roeder\\ } \end{center}\vfill \mbox{}\\ {\mbox{}\\ \small \noindent \textbf{ Marc Roeder\\ } Email: \href{mailto://roeder.marc@gmail.com} {\texttt{roeder.marc@gmail.com}}}\\ \end{titlepage} \newpage\setcounter{page}{2} {\small \section*{Copyright} \logpage{[ 0, 0, 1 ]} {\copyright} 2007 Marc R{\"o}der. This package is distributed under the terms of the GNU General Public License version 2 or later (at your convenience). See the file \texttt{LICENSE} or \href{https://www.gnu.org/copyleft/gpl.html} {\texttt{https://www.gnu.org/copyleft/gpl.html}} \mbox{}}\\[1cm] {\small \section*{Acknowledgements} \logpage{[ 0, 0, 2 ]} This work was supported by Marie Curie Grant No. MTKD\texttt{\symbol{45}}CT\texttt{\symbol{45}}2006\texttt{\symbol{45}}042685 \mbox{}}\\[1cm] \newpage \def\contentsname{Contents\logpage{[ 0, 0, 3 ]}} \tableofcontents \newpage \chapter{\textcolor{Chapter }{Introduction}}\logpage{[ 1, 0, 0 ]} \hyperdef{L}{X7DFB63A97E67C0A1}{} { \section{\textcolor{Chapter }{Abstract and Notation}}\logpage{[ 1, 1, 0 ]} \hyperdef{L}{X813275957BA5B5E0}{} { \textsf{HAPcryst} is an extension for "Homological Algebra Programming" (\textsf{HAP}, \cite{hap}) by Graham Ellis. It uses geometric methods to calculate resolutions for crystallographic groups. In this manual, we will use the terms "space group" and "crystallographic group" synonymous. As usual in \textsf{GAP}, group elements are supposed to act from the right. To emphasize this fact, some functions have names ending in "OnRight" (namely those, which rely on the action from the right). This is also meant to make work with \textsf{HAPcryst} and \textsf{cryst} \cite{cryst} easier. The functions called "somethingStandardSpaceGroup" are supposed to work for standard crystallographic groups on left and right some time in the future. Currently only the versions acting on right are implemented. As in \textsf{cryst} \cite{cryst}, space groups are represented as affine linear groups. For the computations in \textsf{HAPcryst}, crystallographic groups have to be in "standard form". That is, the translation basis has to be the standard basis of the space. This implies that the linear part of a group element need not be orthogonal with respect to the usual scalar product. \subsection{\textcolor{Chapter }{The natural action of crystallographic groups}}\logpage{[ 1, 1, 1 ]} \hyperdef{L}{X7F4A00F481A1FB39}{} { \index{action of crystallographic groups} There is some confusion about the way crystallographic groups are written. This concerns the question if we act on left or on right and if vectors are of the form \texttt{[1,...]} or \texttt{[...,1]}. As mentioned, \textsf{HAPcryst} handles affine crystallographic groups on right (and maybe later also on left) acting on vectors of the form $[...,1]$. \textsc{BUT:} The functions in \textsf{HAPcryst} do not take augmented vectors as input (no leading or ending ones). The handling of vectors is done internally. So in \textsf{HAPcryst}, a crystallographic group is a group of $n\times n$ matrices which acts on a vector space of dimension $n-1$ whose elements are vectors of length $n-1$ (not $n$). Example: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@G:=SpaceGroup(3,4); #This group acts on 3-Space| SpaceGroupOnRightBBNWZ( 3, 2, 1, 1, 2 ) !gapprompt@gap>| !gapinput@Display(Representative(G));| [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] !gapprompt@gap>| !gapinput@OrbitStabilizerInUnitCubeOnRight(G,[1/2,0,0]);| rec( orbit := [ [ 1/2, 0, 0 ], [ 1/2, 1/2, 0 ] ], stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ]) ) \end{Verbatim} } } \section{\textcolor{Chapter }{Requirements}}\logpage{[ 1, 2, 0 ]} \hyperdef{L}{X85A08CF187A6D986}{} { \index{installation} The following \textsf{GAP} packages are required \begin{itemize} \item \textsf{polymaking} which in turn depends on the computational geometry software polymake. \item \textsf{HAP} \item \textsf{Cryst} \end{itemize} The following \textsf{GAP} packages are not required but highly recommended: \begin{itemize} \item \textsf{carat} \item \textsf{CrystCat} \item \textsf{GAPDoc} is needed to display the online manual \end{itemize} \subsection{\textcolor{Chapter }{Recommendation concerning polymake}}\logpage{[ 1, 2, 1 ]} \hyperdef{L}{X7990986A8114E0DB}{} { \index{polymake} Calculating resolutions of Bieberbach groups involves convex hull computations. polymake by default uses cdd to compute convex hulls. Experiments suggest that lrs is the more suitable algorithm for the computations done in HAPcryst than the default cdd. You can change the behaviour of by editing the file "yourhomedirectory/.polymake/prefer.pl". It should contain a section like this (just make sure lrs is before cdd, the position of beneath{\textunderscore}beyond does not matter): \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] ######################################### application polytope; prefer "*.convex_hull lrs, beneath_beyond, cdd"; \end{Verbatim} } } \section{\textcolor{Chapter }{Global Variables}}\logpage{[ 1, 3, 0 ]} \hyperdef{L}{X7D9044767BEB1523}{} { \textsf{HAPcryst} itself does only have one global variable, namely \texttt{InfoHAPcryst} (\ref{InfoHAPcryst}). The location of files generated for interaction with polymake are determined by the value of \texttt{POLYMAKE{\textunderscore}DATA{\textunderscore}DIR} (\textbf{polymaking: POLYMAKE{\textunderscore}DATA{\textunderscore}DIR}) which is a global variable of \textsf{polymaking}. \subsection{\textcolor{Chapter }{InfoHAPcryst}} \logpage{[ 1, 3, 1 ]}\nobreak \hyperdef{L}{X78B0A21E7FD0F3BB}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{InfoHAPcryst\index{InfoHAPcryst@\texttt{InfoHAPcryst}} \label{InfoHAPcryst} }\hfill{\scriptsize (info class)}}\\ At a level of 1, only the most important messages are printed. At level 2, additional information is displayed, and level 3 is even more verbose. At level 0, \textsf{HAPcryst} remains silent. } } } \chapter{\textcolor{Chapter }{Bits and Pieces}}\logpage{[ 2, 0, 0 ]} \hyperdef{L}{X86FBE5B77C2F9442}{} { This chapter contains a few very basic functions which are needed for space group calculations and were missing in standard \textsf{GAP}. \section{\textcolor{Chapter }{Matrices and Vectors}}\logpage{[ 2, 1, 0 ]} \hyperdef{L}{X8019925B8294F5B4}{} { \subsection{\textcolor{Chapter }{SignRat}} \logpage{[ 2, 1, 1 ]}\nobreak \hyperdef{L}{X7D58A1848182EC26}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{SignRat({\mdseries\slshape x})\index{SignRat@\texttt{SignRat}} \label{SignRat} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } sign of the rational number \mbox{\texttt{\mdseries\slshape x}} (Standard \textsf{GAP} currently only has \texttt{SignInt}). } \subsection{\textcolor{Chapter }{VectorModOne}} \logpage{[ 2, 1, 2 ]}\nobreak \hyperdef{L}{X7C0552BA873515B9}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{VectorModOne({\mdseries\slshape v})\index{VectorModOne@\texttt{VectorModOne}} \label{VectorModOne} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } Rational vector of the same length with enties in $[0,1)$ For a rational vector \mbox{\texttt{\mdseries\slshape v}}, this returns the vector with all entries taken "mod 1". } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@SignRat((-4)/(-2));| 1 !gapprompt@gap>| !gapinput@SignRat(9/(-2));| -1 !gapprompt@gap>| !gapinput@VectorModOne([1/10,100/9,5/6,6/5]);| [ 1/10, 1/9, 5/6, 1/5 ] \end{Verbatim} \subsection{\textcolor{Chapter }{IsSquareMat}} \logpage{[ 2, 1, 3 ]}\nobreak \hyperdef{L}{X7BB083A57C474F45}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsSquareMat({\mdseries\slshape matrix})\index{IsSquareMat@\texttt{IsSquareMat}} \label{IsSquareMat} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } \texttt{true} if \mbox{\texttt{\mdseries\slshape matrix}} is a square matrix and \texttt{false} otherwise. } \subsection{\textcolor{Chapter }{DimensionSquareMat}} \logpage{[ 2, 1, 4 ]}\nobreak \hyperdef{L}{X78C932A48515EF10}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DimensionSquareMat({\mdseries\slshape matrix})\index{DimensionSquareMat@\texttt{DimensionSquareMat}} \label{DimensionSquareMat} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } Number of lines in the matrix \mbox{\texttt{\mdseries\slshape matrix}} if it is square and \texttt{fail} otherwise } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@m:=[[1,2,3],[4,5,6],[9,6,12]];| [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 9, 6, 12 ] ] !gapprompt@gap>| !gapinput@IsSquareMat(m);| true !gapprompt@gap>| !gapinput@DimensionSquareMat(m);| 3 !gapprompt@gap>| !gapinput@DimensionSquareMat([[1,2],[1,2,3]]);| fail \end{Verbatim} Affine mappings of $n$ dimensional space are often written as a pair $(A,v)$ where $A$ is a linear mapping and $v$ is a vector. \textsf{GAP} represents affine mappings by $n+1$ times $n+1$ matrices $M$ which satisfy $M_{{n+1,n+1}}=1$ and $M_{{i,n+1}}=0$ for all $1\leq i \leq n$. An affine matrix acts on an $n$ dimensional space which is written as a space of $n+1$ tuples with $n+1$st entry $1$. Here we give two functions to handle these affine matrices. } \section{\textcolor{Chapter }{Affine Matrices OnRight}}\logpage{[ 2, 2, 0 ]} \hyperdef{L}{X86BD4FE4871379AD}{} { \subsection{\textcolor{Chapter }{LinearPartOfAffineMatOnRight}} \logpage{[ 2, 2, 1 ]}\nobreak \hyperdef{L}{X838946957FC75C17}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{LinearPartOfAffineMatOnRight({\mdseries\slshape mat})\index{LinearPartOfAffineMatOnRight@\texttt{LinearPartOfAffineMatOnRight}} \label{LinearPartOfAffineMatOnRight} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } the linear part of the affine matrix \mbox{\texttt{\mdseries\slshape mat}}. That is, everything except for the last row and column. } \subsection{\textcolor{Chapter }{BasisChangeAffineMatOnRight}} \logpage{[ 2, 2, 2 ]}\nobreak \hyperdef{L}{X80DD4F2286D49F8D}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BasisChangeAffineMatOnRight({\mdseries\slshape transform, mat})\index{BasisChangeAffineMatOnRight@\texttt{BasisChangeAffineMatOnRight}} \label{BasisChangeAffineMatOnRight} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } affine matrix with same dimensions as \mbox{\texttt{\mdseries\slshape mat}} A basis change \mbox{\texttt{\mdseries\slshape transform}} of an $n$ dimensional space induces a transformation on affine mappings on this space. If \mbox{\texttt{\mdseries\slshape mat}} is a affine matrix (in particular, it is $(n+1)\times (n+1)$), this method returns the image of \mbox{\texttt{\mdseries\slshape mat}} under the basis transformation induced by \mbox{\texttt{\mdseries\slshape transform}}. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@c:=[[0,1],[1,0]];| [ [ 0, 1 ], [ 1, 0 ] ] !gapprompt@gap>| !gapinput@m:=[[1/2,0,0],[0,2/3,0],[1,0,1]];| [ [ 1/2, 0, 0 ], [ 0, 2/3, 0 ], [ 1, 0, 1 ] ] !gapprompt@gap>| !gapinput@BasisChangeAffineMatOnRight(c,m);| [ [ 2/3, 0, 0 ], [ 0, 1/2, 0 ], [ 0, 1, 1 ] ] \end{Verbatim} \subsection{\textcolor{Chapter }{TranslationOnRightFromVector}} \logpage{[ 2, 2, 3 ]}\nobreak \hyperdef{L}{X81F3C49580958FB6}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{TranslationOnRightFromVector({\mdseries\slshape v})\index{TranslationOnRightFromVector@\texttt{TranslationOnRightFromVector}} \label{TranslationOnRightFromVector} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } Affine matrix Given a vector \mbox{\texttt{\mdseries\slshape v}} with $n$ entries, this method returns a $(n+1)\times (n+1)$ matrix which corresponds to the affine translation defined by \mbox{\texttt{\mdseries\slshape v}}. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@m:=TranslationOnRightFromVector([1,2,3]);;| !gapprompt@gap>| !gapinput@Display(m);| [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 1, 2, 3, 1 ] ] !gapprompt@gap>| !gapinput@LinearPartOfAffineMatOnRight(m);| [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ] !gapprompt@gap>| !gapinput@BasisChangeAffineMatOnRight([[3,2,1],[0,1,0],[0,0,1]],m);| [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 3, 4, 4, 1 ] ] \end{Verbatim} } \section{\textcolor{Chapter }{Geometry}}\logpage{[ 2, 3, 0 ]} \hyperdef{L}{X84A0B0637F269E37}{} { \subsection{\textcolor{Chapter }{GramianOfAverageScalarProductFromFiniteMatrixGroup}} \logpage{[ 2, 3, 1 ]}\nobreak \hyperdef{L}{X7A94DAE679AD73E3}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{GramianOfAverageScalarProductFromFiniteMatrixGroup({\mdseries\slshape G})\index{GramianOfAverageScalarProductFromFiniteMatrixGroup@\texttt{Gramian}\-\texttt{Of}\-\texttt{Average}\-\texttt{Scalar}\-\texttt{Product}\-\texttt{From}\-\texttt{Finite}\-\texttt{Matrix}\-\texttt{Group}} \label{GramianOfAverageScalarProductFromFiniteMatrixGroup} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } Symmetric positive definite matrix For a finite matrix group \mbox{\texttt{\mdseries\slshape G}}, the gramian matrix of the average scalar product is returned. This is the sum over all $gg^t$ with $g\in G$ (actually it is enough to take a generating set). The group \mbox{\texttt{\mdseries\slshape G}} is orthogonal with respect to the scalar product induced by the returned matrix. } \subsection{\textcolor{Chapter }{Inequalities}}\logpage{[ 2, 3, 2 ]} \hyperdef{L}{X866942167802E036}{} { Inequalities are represented in the same way they are represented in \textsf{polymaking}. The vector $(v_0,\ldots,v_n)$ represents the inequality $0\leq v_0+v_1 x_1+\ldots + v_n x_n$. } \subsection{\textcolor{Chapter }{BisectorInequalityFromPointPair}} \logpage{[ 2, 3, 3 ]}\nobreak \hyperdef{L}{X80C365AA87BDDAFA}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BisectorInequalityFromPointPair({\mdseries\slshape v1, v2[, gram]})\index{BisectorInequalityFromPointPair@\texttt{BisectorInequalityFromPointPair}} \label{BisectorInequalityFromPointPair} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } vector of length \texttt{Length(v1)+1} Calculates the inequality defining the half\texttt{\symbol{45}}space containing \mbox{\texttt{\mdseries\slshape v1}} such that \texttt{\mbox{\texttt{\mdseries\slshape v1}}\texttt{\symbol{45}}\mbox{\texttt{\mdseries\slshape v2}}} is perpendicular on the bounding hyperplane. And \texttt{(\mbox{\texttt{\mdseries\slshape v1}}\texttt{\symbol{45}}\mbox{\texttt{\mdseries\slshape v2}})/2} is contained in the bounding hyperplane.\\ If the matrix \mbox{\texttt{\mdseries\slshape gram}} is given, it is used as the gramian matrix. Otherwiese, the standard scalar product is used. It is not checked if \mbox{\texttt{\mdseries\slshape gram}} is positive definite or symmetric. } \subsection{\textcolor{Chapter }{WhichSideOfHyperplane}} \logpage{[ 2, 3, 4 ]}\nobreak \hyperdef{L}{X8790464D86D189F4}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{WhichSideOfHyperplane({\mdseries\slshape v, ineq})\index{WhichSideOfHyperplane@\texttt{WhichSideOfHyperplane}} \label{WhichSideOfHyperplane} }\hfill{\scriptsize (method)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{WhichSideOfHyperplaneNC({\mdseries\slshape v, ineq})\index{WhichSideOfHyperplaneNC@\texttt{WhichSideOfHyperplaneNC}} \label{WhichSideOfHyperplaneNC} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } \texttt{\symbol{45}}1 (below) 0 (in) or 1 (above). Let \mbox{\texttt{\mdseries\slshape v}} be a vector of length $n$ and \mbox{\texttt{\mdseries\slshape ineq}} an inequality represented by a vector of length $n+1$. Then \texttt{WhichSideOfHyperplane(\mbox{\texttt{\mdseries\slshape v, ineq}})} returns 1 if \mbox{\texttt{\mdseries\slshape v}} is a solution of the inequality but not the equation given by \mbox{\texttt{\mdseries\slshape ineq}}, it returns 0 if \mbox{\texttt{\mdseries\slshape v}} is a solution to the equation and \texttt{\symbol{45}}1 if it is not a solution of the inequality \mbox{\texttt{\mdseries\slshape ineq}}. The NC version does not test the input for correctness. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@BisectorInequalityFromPointPair([0,0],[1,0]);| [ 1, -2, 0 ] !gapprompt@gap>| !gapinput@ineq:=BisectorInequalityFromPointPair([0,0],[1,0],[[5,4],[4,5]]);| [ 5, -10, -8 ] !gapprompt@gap>| !gapinput@ineq{[2,3]}*[1/2,0];| -5 !gapprompt@gap>| !gapinput@WhichSideOfHyperplane([0,0],ineq);| 1 !gapprompt@gap>| !gapinput@WhichSideOfHyperplane([1/2,0],ineq);| 0 \end{Verbatim} \subsection{\textcolor{Chapter }{RelativePositionPointAndPolygon}} \logpage{[ 2, 3, 5 ]}\nobreak \hyperdef{L}{X83392C417B311B6B}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{RelativePositionPointAndPolygon({\mdseries\slshape point, poly})\index{RelativePositionPointAndPolygon@\texttt{RelativePositionPointAndPolygon}} \label{RelativePositionPointAndPolygon} }\hfill{\scriptsize (operation)}}\\ \textbf{\indent Returns:\ } one of \texttt{"VERTEX", "FACET", "OUTSIDE", "INSIDE"} Let \mbox{\texttt{\mdseries\slshape poly}} be a \texttt{PolymakeObject} and \mbox{\texttt{\mdseries\slshape point}} a vector. If \mbox{\texttt{\mdseries\slshape point}} is a vertex of \mbox{\texttt{\mdseries\slshape poly}}, the string \texttt{"VERTEX"} is returned. If \mbox{\texttt{\mdseries\slshape point}} lies inside \mbox{\texttt{\mdseries\slshape poly}}, \texttt{"INSIDE"} is returned and if it lies in a facet, \texttt{"FACET"} is returned and if \mbox{\texttt{\mdseries\slshape point}} does not lie inside \mbox{\texttt{\mdseries\slshape poly}}, the function returns \texttt{"OUTSIDE"}. } } \section{\textcolor{Chapter }{Space Groups}}\logpage{[ 2, 4, 0 ]} \hyperdef{L}{X7B14774981F80108}{} { \subsection{\textcolor{Chapter }{PointGroupRepresentatives}} \logpage{[ 2, 4, 1 ]}\nobreak \hyperdef{L}{X7E2F20607F278B70}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{PointGroupRepresentatives({\mdseries\slshape group})\index{PointGroupRepresentatives@\texttt{PointGroupRepresentatives}} \label{PointGroupRepresentatives} }\hfill{\scriptsize (attribute)}}\\ \textbf{\indent Returns:\ } list of matrices Given an \texttt{AffineCrystGroupOnLeftOrRight} \mbox{\texttt{\mdseries\slshape group}}, this returns a list of representatives of the point group of \mbox{\texttt{\mdseries\slshape group}}. That is, a system of representatives for the factor group modulo translations. This is an attribute of \texttt{AffineCrystGroupOnLeftOrRight} } } } \chapter{\textcolor{Chapter }{Algorithms of Orbit\texttt{\symbol{45}}Stabilizer Type}}\logpage{[ 3, 0, 0 ]} \hyperdef{L}{X7F6789767FB36E74}{} { We introduce a way to calculate a sufficient part of an orbit and the stabilizer of a point. \section{\textcolor{Chapter }{Orbit Stabilizer for Crystallographic Groups}}\logpage{[ 3, 1, 0 ]} \hyperdef{L}{X85CAB2EB85A6E17A}{} { \subsection{\textcolor{Chapter }{OrbitStabilizerInUnitCubeOnRight}} \logpage{[ 3, 1, 1 ]}\nobreak \hyperdef{L}{X7BED233684B2F811}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{OrbitStabilizerInUnitCubeOnRight({\mdseries\slshape group, x})\index{OrbitStabilizerInUnitCubeOnRight@\texttt{OrbitStabilizerInUnitCubeOnRight}} \label{OrbitStabilizerInUnitCubeOnRight} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } A record containing \begin{itemize} \item \texttt{.stabilizer}: the stabilizer of \mbox{\texttt{\mdseries\slshape x}}. \item \texttt{.orbit} set of vectors from $[0,1)^n$ which represents the orbit. \end{itemize} Let \mbox{\texttt{\mdseries\slshape x}} be a rational vector from $[0,1)^n$ and \mbox{\texttt{\mdseries\slshape group}} a space group in standard form. The function then calculates the part of the orbit which lies inside the cube $[0,1)^n$ and the stabilizer of \mbox{\texttt{\mdseries\slshape x}}. Observe that every element of the full orbit differs from a point in the returned orbit only by a pure translation. } Note that the restriction to points from $[0,1)^n$ makes sense if orbits should be compared and the vector passed to \texttt{OrbitStabilizerInUnitCubeOnRight} should be an element of the returned orbit (part). \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@S:=SpaceGroup(3,5);;| !gapprompt@gap>| !gapinput@OrbitStabilizerInUnitCubeOnRight(S,[1/2,0,9/11]); | rec( orbit := [ [ 0, 1/2, 2/11 ], [ 1/2, 0, 9/11 ] ], stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ]) ) !gapprompt@gap>| !gapinput@OrbitStabilizerInUnitCubeOnRight(S,[0,0,0]); | rec( orbit := [ [ 0, 0, 0 ] ], stabilizer := ) \end{Verbatim} If you are interested in other parts of the orbit, you can use \texttt{VectorModOne} (\ref{VectorModOne}) for the base point and the functions \texttt{ShiftedOrbitPart} (\ref{ShiftedOrbitPart}), \texttt{TranslationsToOneCubeAroundCenter} (\ref{TranslationsToOneCubeAroundCenter}) and \texttt{TranslationsToBox} (\ref{TranslationsToBox}) for the resulting orbit\\ Suppose we want to calculate the part of the orbit of \texttt{[4/3,5/3,7/3]} in the cube of sidelength \texttt{1} around this point: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@S:=SpaceGroup(3,5);;| !gapprompt@gap>| !gapinput@p:=[4/3,5/3,7/3];;| !gapprompt@gap>| !gapinput@o:=OrbitStabilizerInUnitCubeOnRight(S,VectorModOne(p)).orbit;| [ [ 1/3, 2/3, 1/3 ], [ 1/3, 2/3, 2/3 ] ] !gapprompt@gap>| !gapinput@box:=p+[[-1,1],[-1,1],[-1,1]];| [ [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ] ] !gapprompt@gap>| !gapinput@o2:=Concatenation(List(o,i->i+TranslationsToBox(i,box)));;| !gapprompt@gap>| !gapinput@# This is what we looked for. But it is somewhat large:| !gapprompt@gap>| !gapinput@Size(o2);| 54 \end{Verbatim} \subsection{\textcolor{Chapter }{OrbitStabilizerInUnitCubeOnRightOnSets}} \logpage{[ 3, 1, 2 ]}\nobreak \hyperdef{L}{X82BD20307A67C119}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{OrbitStabilizerInUnitCubeOnRightOnSets({\mdseries\slshape group, set})\index{OrbitStabilizerInUnitCubeOnRightOnSets@\texttt{Orbit}\-\texttt{Stabilizer}\-\texttt{In}\-\texttt{Unit}\-\texttt{Cube}\-\texttt{On}\-\texttt{Right}\-\texttt{On}\-\texttt{Sets}} \label{OrbitStabilizerInUnitCubeOnRightOnSets} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } A record containing \begin{itemize} \item \texttt{.stabilizer}: the stabilizer of \mbox{\texttt{\mdseries\slshape set}}. \item \texttt{.orbit} set of sets of vectors from $[0,1)^n$ which represents the orbit. \end{itemize} Calculates orbit and stabilizer of a set of vectors. Just as \texttt{OrbitStabilizerInUnitCubeOnRight} (\ref{OrbitStabilizerInUnitCubeOnRight}), it needs input from $[0,1)^n$. The returned orbit part \texttt{.orbit} is a set of sets such that every element of \texttt{.orbit} has a non\texttt{\symbol{45}}trivial intersection with the cube $[0,1)^n$. In general, these sets will not lie inside $[0,1)^n$ completely. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@S:=SpaceGroup(3,5);;| !gapprompt@gap>| !gapinput@OrbitStabilizerInUnitCubeOnRightOnSets(S,[[0,0,0],[0,1/2,0]]);| rec( orbit := [ [ [ -1/2, 0, 0 ], [ 0, 0, 0 ] ], [ [ 0, 0, 0 ], [ 0, 1/2, 0 ] ], [ [ 1/2, 0, 0 ], [ 1, 0, 0 ] ] ], stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ]) ) \end{Verbatim} \subsection{\textcolor{Chapter }{OrbitPartInVertexSetsStandardSpaceGroup}} \logpage{[ 3, 1, 3 ]}\nobreak \hyperdef{L}{X82CCCD597C86A08A}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{OrbitPartInVertexSetsStandardSpaceGroup({\mdseries\slshape group, vertexset, allvertices})\index{OrbitPartInVertexSetsStandardSpaceGroup@\texttt{Orbit}\-\texttt{Part}\-\texttt{In}\-\texttt{Vertex}\-\texttt{Sets}\-\texttt{Standard}\-\texttt{Space}\-\texttt{Group}} \label{OrbitPartInVertexSetsStandardSpaceGroup} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } Set of subsets of \mbox{\texttt{\mdseries\slshape allvertices}}. If \mbox{\texttt{\mdseries\slshape allvertices}} is a set of vectors and \mbox{\texttt{\mdseries\slshape vertexset}} is a subset thereof, then \texttt{OrbitPartInVertexSetsStandardSpaceGroup} returns that part of the orbit of \mbox{\texttt{\mdseries\slshape vertexset}} which consists entirely of subsets of \mbox{\texttt{\mdseries\slshape allvertices}}. Note that,unlike the other \texttt{OrbitStabilizer} algorithms, this does not require the input to lie in some particular part of the space. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@S:=SpaceGroup(3,5);;| !gapprompt@gap>| !gapinput@OrbitPartInVertexSetsStandardSpaceGroup(S,[[0,1,5],[1,2,0]],| !gapprompt@>| !gapinput@Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]]));| [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 2, 6 ], [ 2, 3, 1 ] ] ] !gapprompt@gap>| !gapinput@OrbitPartInVertexSetsStandardSpaceGroup(S, [[1,2,0]],| !gapprompt@>| !gapinput@Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]]));| [ [ [ 0, 1, 5 ] ], [ [ 1, 1, 0 ] ], [ [ 1, 2, 0 ] ], [ [ 1, 2, 6 ] ], [ [ 2, 3, 1 ] ] ] \end{Verbatim} \subsection{\textcolor{Chapter }{OrbitPartInFacesStandardSpaceGroup}} \logpage{[ 3, 1, 4 ]}\nobreak \hyperdef{L}{X8022CD75819DE536}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{OrbitPartInFacesStandardSpaceGroup({\mdseries\slshape group, vertexset, faceset})\index{OrbitPartInFacesStandardSpaceGroup@\texttt{OrbitPartInFacesStandardSpaceGroup}} \label{OrbitPartInFacesStandardSpaceGroup} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } Set of subsets of \mbox{\texttt{\mdseries\slshape faceset}}. This calculates the orbit of a space group on sets restricted to a set of faces.\\ If \mbox{\texttt{\mdseries\slshape faceset}} is a set of sets of vectors and \mbox{\texttt{\mdseries\slshape vertexset}} is an element of \mbox{\texttt{\mdseries\slshape faceset}}, then \texttt{OrbitPartInFacesStandardSpaceGroup} returns that part of the orbit of \mbox{\texttt{\mdseries\slshape vertexset}} which consists entirely of elements of \mbox{\texttt{\mdseries\slshape faceset}}.\\ Note that,unlike the other \texttt{OrbitStabilizer} algorithms, this does not require the input to lie in some particular part of the space. } \subsection{\textcolor{Chapter }{OrbitPartAndRepresentativesInFacesStandardSpaceGroup}} \logpage{[ 3, 1, 5 ]}\nobreak \hyperdef{L}{X86A80FA17A4D6664}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{OrbitPartAndRepresentativesInFacesStandardSpaceGroup({\mdseries\slshape group, vertexset, faceset})\index{OrbitPartAndRepresentativesInFacesStandardSpaceGroup@\texttt{Orbit}\-\texttt{Part}\-\texttt{And}\-\texttt{Representatives}\-\texttt{In}\-\texttt{Faces}\-\texttt{Standard}\-\texttt{Space}\-\texttt{Group}} \label{OrbitPartAndRepresentativesInFacesStandardSpaceGroup} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } A set of face\texttt{\symbol{45}}matrix pairs . This is a slight variation of \texttt{OrbitPartInFacesStandardSpaceGroup} (\ref{OrbitPartInFacesStandardSpaceGroup}) that also returns a representative for every orbit element. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@S:=SpaceGroup(3,5);;| !gapprompt@gap>| !gapinput@OrbitPartInVertexSetsStandardSpaceGroup(S,[[0,1,5],[1,2,0]],| !gapprompt@>| !gapinput@Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]]));| [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 2, 6 ], [ 2, 3, 1 ] ] ] !gapprompt@gap>| !gapinput@OrbitPartInFacesStandardSpaceGroup(S,[[0,1,5],[1,2,0]],| !gapprompt@>| !gapinput@Set( [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [[1/17,6,1/2],[1,2,7]]]));| [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ] ] !gapprompt@gap>| !gapinput@OrbitPartAndRepresentativesInFacesStandardSpaceGroup(S,[[0,1,5],[1,2,0]],| !gapprompt@>| !gapinput@Set( [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [[1/17,6,1/2],[1,2,7]]]));| [ [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ] ] \end{Verbatim} \subsection{\textcolor{Chapter }{StabilizerOnSetsStandardSpaceGroup}} \logpage{[ 3, 1, 6 ]}\nobreak \hyperdef{L}{X81DE08687F0DBCC6}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{StabilizerOnSetsStandardSpaceGroup({\mdseries\slshape group, set})\index{StabilizerOnSetsStandardSpaceGroup@\texttt{StabilizerOnSetsStandardSpaceGroup}} \label{StabilizerOnSetsStandardSpaceGroup} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } finite group of affine matrices (OnRight) Given a set \mbox{\texttt{\mdseries\slshape set}} of vectors and a space group \mbox{\texttt{\mdseries\slshape group}} in standard form, this method calculates the stabilizer of that set in the full crystallographic group.\\ } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@G:=SpaceGroup(3,12);;| !gapprompt@gap>| !gapinput@v:=[ 0, 0,0 ];;| !gapprompt@gap>| !gapinput@s:=StabilizerOnSetsStandardSpaceGroup(G,[v]);| !gapprompt@gap>| !gapinput@s2:=OrbitStabilizerInUnitCubeOnRight(G,v).stabilizer;| !gapprompt@gap>| !gapinput@s2=s;| true \end{Verbatim} \subsection{\textcolor{Chapter }{RepresentativeActionOnRightOnSets}} \logpage{[ 3, 1, 7 ]}\nobreak \hyperdef{L}{X83C6448679A54F9D}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{RepresentativeActionOnRightOnSets({\mdseries\slshape group, set, imageset})\index{RepresentativeActionOnRightOnSets@\texttt{RepresentativeActionOnRightOnSets}} \label{RepresentativeActionOnRightOnSets} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } Affine matrix. Returns an element of the space group $S$ which takes the set \mbox{\texttt{\mdseries\slshape set}} to the set \mbox{\texttt{\mdseries\slshape imageset}}. The group must be in standard form and act on the right. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@S:=SpaceGroup(3,5);;| !gapprompt@gap>| !gapinput@RepresentativeActionOnRightOnSets(G, [[0,0,0],[0,1/2,0]],| !gapprompt@>| !gapinput@ [ [ 0, 1/2, 0 ], [ 0, 1, 0 ] ]);| [ [ 0, -1, 0, 0 ], [ -1, 0, 0, 0 ], [ 0, 0, -1, 0 ], [ 0, 1, 0, 1 ] ] \end{Verbatim} \subsection{\textcolor{Chapter }{Getting other orbit parts}}\logpage{[ 3, 1, 8 ]} \hyperdef{L}{X8002407080DB3EA2}{} { \textsf{HAPcryst} does not calculate the full orbit but only the part of it having coefficients between $-1/2$ and $1/2$. The other parts of the orbit can be calculated using the following functions. } \subsection{\textcolor{Chapter }{ShiftedOrbitPart}} \logpage{[ 3, 1, 9 ]}\nobreak \hyperdef{L}{X8751429287034F4A}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ShiftedOrbitPart({\mdseries\slshape point, orbitpart})\index{ShiftedOrbitPart@\texttt{ShiftedOrbitPart}} \label{ShiftedOrbitPart} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } Set of vectors Takes each vector in \mbox{\texttt{\mdseries\slshape orbitpart}} to the cube unit cube centered in \mbox{\texttt{\mdseries\slshape point}}. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@ShiftedOrbitPart([0,0,0],[[1/2,1/2,1/3],-[1/2,1/2,1/2],[19,3,1]]);| [ [ 1/2, 1/2, 1/3 ], [ 1/2, 1/2, 1/2 ], [ 0, 0, 0 ] ] !gapprompt@gap>| !gapinput@ShiftedOrbitPart([1,1,1],[[1/2,1/2,1/2],-[1/2,1/2,1/2]]);| [ [ 3/2, 3/2, 3/2 ] ] \end{Verbatim} \subsection{\textcolor{Chapter }{TranslationsToOneCubeAroundCenter}} \logpage{[ 3, 1, 10 ]}\nobreak \hyperdef{L}{X82656DE584E8DC5D}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{TranslationsToOneCubeAroundCenter({\mdseries\slshape point, center})\index{TranslationsToOneCubeAroundCenter@\texttt{TranslationsToOneCubeAroundCenter}} \label{TranslationsToOneCubeAroundCenter} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } List of integer vectors This method returns the list of all integer vectors which translate \mbox{\texttt{\mdseries\slshape point}} into the box \mbox{\texttt{\mdseries\slshape center}}$+[-1/2,1/2]^n$ } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@TranslationsToOneCubeAroundCenter([1/2,1/2,1/3],[0,0,0]);| [ [ 0, 0, 0 ], [ 0, -1, 0 ], [ -1, 0, 0 ], [ -1, -1, 0 ] ] !gapprompt@gap>| !gapinput@TranslationsToOneCubeAroundCenter([1,0,1],[0,0,0]);| [ [ -1, 0, -1 ] ] \end{Verbatim} \subsection{\textcolor{Chapter }{TranslationsToBox}} \logpage{[ 3, 1, 11 ]}\nobreak \hyperdef{L}{X858C787E83A902AB}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{TranslationsToBox({\mdseries\slshape point, box})\index{TranslationsToBox@\texttt{TranslationsToBox}} \label{TranslationsToBox} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } List of integer vectors or the empty list Given a vector $v$ and a list of pairs, this function returns the translation vectors (integer vectors) which take $v$ into the box \mbox{\texttt{\mdseries\slshape box}}. The box \mbox{\texttt{\mdseries\slshape box}} has to be given as a list of pairs. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@TranslationsToBox([0,0],[[1/2,2/3],[1/2,2/3]]);| [ ] !gapprompt@gap>| !gapinput@TranslationsToBox([0,0],[[-3/2,1/2],[1,4/3]]);| [ [ -1, 1 ], [ 0, 1 ] ] !gapprompt@gap>| !gapinput@TranslationsToBox([0,0],[[-3/2,1/2],[2,1]]);| Error, Box must not be empty \end{Verbatim} } } \chapter{\textcolor{Chapter }{Resolutions of Crystallographic Groups}}\logpage{[ 4, 0, 0 ]} \hyperdef{L}{X852C41A77C759D82}{} { \section{\textcolor{Chapter }{Fundamental Domains}}\logpage{[ 4, 1, 0 ]} \hyperdef{L}{X7F48638F817A14B0}{} { Let $S$ be a crystallographic group. A Fundamental domain is a closed convex set containing a system of representatives for the Orbits of $S$ in its natural action on euclidian space.\\ There are two algorithms for calculating fundamental domains in \textsf{HAPcryst}. One uses the geometry and relies on having the standard rule for evaluating the scalar product (i.e. the gramian matrix is the identity). The other one is independent of the gramian matrix but does only work for Bieberbach groups, while the first ("geometric") algorithm works for arbitrary crystallographic groups given a point with trivial stabilizer. \subsection{\textcolor{Chapter }{FundamentalDomainStandardSpaceGroup}} \logpage{[ 4, 1, 1 ]}\nobreak \hyperdef{L}{X79F4F7938116201E}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{FundamentalDomainStandardSpaceGroup({\mdseries\slshape [v, ]G})\index{FundamentalDomainStandardSpaceGroup@\texttt{FundamentalDomainStandardSpaceGroup}} \label{FundamentalDomainStandardSpaceGroup} }\hfill{\scriptsize (operation)}}\\ \textbf{\indent Returns:\ } a \texttt{PolymakeObject} Let \mbox{\texttt{\mdseries\slshape G}} be an \texttt{AffineCrystGroupOnRight} and \mbox{\texttt{\mdseries\slshape v}} a vector. A fundamental domain containing \mbox{\texttt{\mdseries\slshape v}} is calculated and returned as a \texttt{PolymakeObject}. The vector \mbox{\texttt{\mdseries\slshape v}} is used as the starting point for a Dirichlet\texttt{\symbol{45}}Voronoi construction. If no \mbox{\texttt{\mdseries\slshape v}} is given, the origin is used as starting point if it has trivial stabiliser. Otherwise an error is cast. \\ } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@fd:=FundamentalDomainStandardSpaceGroup([1/2,0,1/5],SpaceGroup(3,9));| !gapprompt@gap>| !gapinput@Polymake(fd,"N_VERTICES");| 24 !gapprompt@gap>| !gapinput@fd:=FundamentalDomainStandardSpaceGroup(SpaceGroup(3,9));| !gapprompt@gap>| !gapinput@Polymake(fd,"N_VERTICES");| 8 \end{Verbatim} \subsection{\textcolor{Chapter }{FundamentalDomainBieberbachGroup}} \logpage{[ 4, 1, 2 ]}\nobreak \hyperdef{L}{X7A07AB55831F212F}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{FundamentalDomainBieberbachGroup({\mdseries\slshape [v, ]G[, gram]})\index{FundamentalDomainBieberbachGroup@\texttt{FundamentalDomainBieberbachGroup}} \label{FundamentalDomainBieberbachGroup} }\hfill{\scriptsize (operation)}}\\ \textbf{\indent Returns:\ } a \texttt{PolymakeObject} Given a starting vector \mbox{\texttt{\mdseries\slshape v}} and a Bieberbach group \mbox{\texttt{\mdseries\slshape G}} in standard form, this method calculates the Dirichlet domain with respect to \mbox{\texttt{\mdseries\slshape v}}. If \mbox{\texttt{\mdseries\slshape gram}} is not supplied, the average gramian matrix is used (see \texttt{GramianOfAverageScalarProductFromFiniteMatrixGroup} (\ref{GramianOfAverageScalarProductFromFiniteMatrixGroup})). It is not tested if \mbox{\texttt{\mdseries\slshape gram}} is symmetric and positive definite. It is also not tested, if the product defined by \mbox{\texttt{\mdseries\slshape gram}} is invariant under the point group of \mbox{\texttt{\mdseries\slshape G}}. The behaviour of this function is influenced by the option \texttt{ineqThreshold}\label{ineqThreshold}\index{ineqThreshold}. The algorithm calculates approximations to a fundamental domain by iteratively adding inequalities. For an approximating polyhedron, every vertex is tested to find new inequalities. When all vertices have been considered or the number of new inequalities already found exceeds the value of \texttt{ineqThreshold}, a new approximating polyhedron in calculated. The default for \texttt{ineqThreshold} is 200. Roughly speaking, a large threshold means shifting work from \texttt{polymake} to \textsf{GAP}, a small one means more calls of (and work for) \texttt{polymake}. If the value of \texttt{InfoHAPcryst} (\ref{InfoHAPcryst}) is 2 or more, for each approximation the number of vertices of the approximation, the number of vertices that have to be considered during the calculation, the number of facets, and new inequalities is shown. Note that the algorithm chooses vertices in random order and also writes inequalities for \texttt{polymake} in random order. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@a0:=[[ 1, 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0, 0 ], | !gapprompt@>| !gapinput@ [ 0, 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 0 ], | !gapprompt@>| !gapinput@ [ 0, 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, -1, -1, 0 ],| !gapprompt@>| !gapinput@ [ -1/2, 0, 0, 1/6, 0, 0, 1 ] | !gapprompt@>| !gapinput@ ];;| !gapprompt@gap>| !gapinput@a1:=[[ 0, -1, 0, 0, 0, 0, 0 ],[ 0, 0, -1, 0, 0, 0, 0 ],| !gapprompt@>| !gapinput@ [ 1, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 0 ], | !gapprompt@>| !gapinput@ [ 0, 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 1, 0 ],| !gapprompt@>| !gapinput@ [ 0, 0, 0, 0, 1/3, -1/3, 1 ] | !gapprompt@>| !gapinput@ ];;| !gapprompt@gap>| !gapinput@trans:=List(Group((1,2,3,4,5,6)),g->| !gapprompt@>| !gapinput@ TranslationOnRightFromVector(Permuted([1,0,0,0,0,0],g)));;| !gapprompt@gap>| !gapinput@S:=AffineCrystGroupOnRight(Concatenation(trans,[a0,a1]));| !gapprompt@gap>| !gapinput@SetInfoLevel(InfoHAPcryst,2);| !gapprompt@gap>| !gapinput@FundamentalDomainBieberbachGroup(S:ineqThreshold:=10);| #I v: 104/104 f:15 #I new: 201 #I v: 961/961 f:58 #I new: 20 #I v: 1143/805 f:69 #I new: 12 #I v: 1059/555 f:64 #I new: 15 #I v: 328/109 f:33 #I new: 12 #I v: 336/58 f:32 #I new: 0 !gapprompt@gap>| !gapinput@FundamentalDomainBieberbachGroup(S:ineqThreshold:=1000);| #I v: 104/104 f:15 #I new: 149 #I v: 635/635 f:41 #I new: 115 #I v: 336/183 f:32 #I new: 0 #I out of inequalities \end{Verbatim} \subsection{\textcolor{Chapter }{FundamentalDomainFromGeneralPointAndOrbitPartGeometric}} \logpage{[ 4, 1, 3 ]}\nobreak \hyperdef{L}{X86A09AC4842827C9}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{FundamentalDomainFromGeneralPointAndOrbitPartGeometric({\mdseries\slshape v, orbit})\index{FundamentalDomainFromGeneralPointAndOrbitPartGeometric@\texttt{Fundamental}\-\texttt{Domain}\-\texttt{From}\-\texttt{General}\-\texttt{Point}\-\texttt{And}\-\texttt{Orbit}\-\texttt{Part}\-\texttt{Geometric}} \label{FundamentalDomainFromGeneralPointAndOrbitPartGeometric} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } a \texttt{PolymakeObject} This uses an alternative algorithm based on geometric considerations. It is not used in any of the high\texttt{\symbol{45}}level methods. Let \mbox{\texttt{\mdseries\slshape v}} be a vector and \mbox{\texttt{\mdseries\slshape orbit}} a sufficiently large part of the orbit of \mbox{\texttt{\mdseries\slshape v}} under a crystallographic group with standard\texttt{\symbol{45}} orthogonal point group (satisfying $A^t=A^-1$). A geometric algorithm is then used to calculate the Dirichlet domain with respect to \mbox{\texttt{\mdseries\slshape v}}. This also works for crystallographic groups which are not Bieberbach. The point \mbox{\texttt{\mdseries\slshape v}} has to have trivial stabilizer.\\ The intersection of the full orbit with the unit cube around \mbox{\texttt{\mdseries\slshape v}} is sufficiently large. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@G:=SpaceGroup(3,9);;| !gapprompt@gap>| !gapinput@v:=[0,0,0];| [ 0, 0, 0 ] !gapprompt@gap>| !gapinput@orbit:=OrbitStabilizerInUnitCubeOnRight(G,v).orbit;| [ [ 0, 0, 0 ], [ 0, 0, 1/2 ] ] !gapprompt@gap>| !gapinput@fd:=FundamentalDomainFromGeneralPointAndOrbitPartGeometric(v,orbit);| !gapprompt@gap>| !gapinput@Polymake(fd,"N_VERTICES");| 8 \end{Verbatim} \subsection{\textcolor{Chapter }{IsFundamentalDomainStandardSpaceGroup}} \logpage{[ 4, 1, 4 ]}\nobreak \hyperdef{L}{X824BC99584F5F865}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsFundamentalDomainStandardSpaceGroup({\mdseries\slshape poly, G})\index{IsFundamentalDomainStandardSpaceGroup@\texttt{IsFundamental}\-\texttt{Domain}\-\texttt{Standard}\-\texttt{Space}\-\texttt{Group}} \label{IsFundamentalDomainStandardSpaceGroup} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } true or false This tests if a \texttt{PolymakeObject} \mbox{\texttt{\mdseries\slshape poly}} is a fundamental domain for the affine crystallographic group \mbox{\texttt{\mdseries\slshape G}} in standard form.\\ The function tests the following: First, does the orbit of any vertex of \mbox{\texttt{\mdseries\slshape poly}} have a point inside \mbox{\texttt{\mdseries\slshape poly}} (if this is the case, \texttt{false} is returned). Second: Is every facet of \mbox{\texttt{\mdseries\slshape poly}} the image of a different facet under a group element which does not fix \mbox{\texttt{\mdseries\slshape poly}}. If this is satisfied, \texttt{true} is returned. } \subsection{\textcolor{Chapter }{IsFundamentalDomainBieberbachGroup}} \logpage{[ 4, 1, 5 ]}\nobreak \hyperdef{L}{X7D79DD6E87BCC1DC}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsFundamentalDomainBieberbachGroup({\mdseries\slshape poly, G})\index{IsFundamentalDomainBieberbachGroup@\texttt{IsFundamentalDomainBieberbachGroup}} \label{IsFundamentalDomainBieberbachGroup} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } true, false or fail This tests if a \texttt{PolymakeObject} \mbox{\texttt{\mdseries\slshape poly}} is a fundamental domain for the affine crystallographic group \mbox{\texttt{\mdseries\slshape G}} in standard form and if this group is torsion free (ie a Bieberbach group)\\ It returns \texttt{true} if \mbox{\texttt{\mdseries\slshape G}} is torsion free and \mbox{\texttt{\mdseries\slshape poly}} is a fundamental domain for \mbox{\texttt{\mdseries\slshape G}}. If \mbox{\texttt{\mdseries\slshape poly}} is not a fundamental domain, \texttt{false} is returned regardless of the structure of \mbox{\texttt{\mdseries\slshape G}}. And if \mbox{\texttt{\mdseries\slshape G}} is not torsion free, the method returns \texttt{fail}. If \mbox{\texttt{\mdseries\slshape G}} is polycyclic, torsion freeness is tested using a representation as pcp group. Otherwise the stabilisers of the faces of the fundamental domain \mbox{\texttt{\mdseries\slshape poly}} are calculated (\mbox{\texttt{\mdseries\slshape G}} is torsion free if and only if it all these stabilisers are trivial). } } \section{\textcolor{Chapter }{Face Lattice and Resolution}}\logpage{[ 4, 2, 0 ]} \hyperdef{L}{X78D68F6087238F97}{} { For Bieberbach groups (torsion free crystallographic groups), the following functions calcualte free resolutions. This calculation is done by finding a fundamental domain for the group. For a description of the \texttt{HapResolution} datatype, see the \textsf{Hap} data types documentation or the experimental datatypes documentation \ref{hapresolution} \subsection{\textcolor{Chapter }{ResolutionBieberbachGroup}} \logpage{[ 4, 2, 1 ]}\nobreak \hyperdef{L}{X7CA87AA478007468}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ResolutionBieberbachGroup({\mdseries\slshape G[, v]})\index{ResolutionBieberbachGroup@\texttt{ResolutionBieberbachGroup}} \label{ResolutionBieberbachGroup} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } a \texttt{HAPresolution} Let \mbox{\texttt{\mdseries\slshape G}} be a Bieberbach group given as an \texttt{AffineCrystGroupOnRight} and \mbox{\texttt{\mdseries\slshape v}} a vector. Then a Dirichlet domain with respect to \mbox{\texttt{\mdseries\slshape v}} is calculated using \texttt{FundamentalDomainBieberbachGroup} (\ref{FundamentalDomainBieberbachGroup}). From this domain, a resolution is calculated using \texttt{FaceLatticeAndBoundaryBieberbachGroup} (\ref{FaceLatticeAndBoundaryBieberbachGroup}) and \texttt{ResolutionFromFLandBoundary} (\ref{ResolutionFromFLandBoundary}). If \mbox{\texttt{\mdseries\slshape v}} is not given, the origin is used. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@R:=ResolutionBieberbachGroup(SpaceGroup(3,9));| Resolution of length 3 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 2, 2, 2, 2 ) . No contracting homotopy available. !gapprompt@gap>| !gapinput@List([0..3],Dimension(R));| [ 1, 3, 3, 1 ] !gapprompt@gap>| !gapinput@R:=ResolutionBieberbachGroup(SpaceGroup(3,9),[1/2,0,0]);| Resolution of length 3 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 2, 2, 2, 2 ) . No contracting homotopy available. !gapprompt@gap>| !gapinput@List([0..3],Dimension(R));| [ 6, 12, 7, 1 ] \end{Verbatim} \subsection{\textcolor{Chapter }{FaceLatticeAndBoundaryBieberbachGroup}} \logpage{[ 4, 2, 2 ]}\nobreak \hyperdef{L}{X7E854FC47F9E479E}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{FaceLatticeAndBoundaryBieberbachGroup({\mdseries\slshape poly, group})\index{FaceLatticeAndBoundaryBieberbachGroup@\texttt{Face}\-\texttt{Lattice}\-\texttt{And}\-\texttt{Boundary}\-\texttt{Bieberbach}\-\texttt{Group}} \label{FaceLatticeAndBoundaryBieberbachGroup} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } Record with entries \texttt{.hasse} and \texttt{.elts} representing a part of the hasse diagram and a lookup table of group elements Let \mbox{\texttt{\mdseries\slshape group}} be a torsion free \texttt{AffineCrystGroupOnRight} (that is, a Bieberbach group). Given a \texttt{PolymakeObject} \mbox{\texttt{\mdseries\slshape poly}} representing a fundamental domain for \mbox{\texttt{\mdseries\slshape group}}, this method uses \textsf{polymaking} to calculate the face lattice of \mbox{\texttt{\mdseries\slshape poly}}. From the set of faces, a system of representatives for \mbox{\texttt{\mdseries\slshape group}}\texttt{\symbol{45}} orbits is chosen. For each representative, the boundary is then calculated. The list \texttt{.elts} contains elements of \mbox{\texttt{\mdseries\slshape group}} (in fact, it is even a set). The structure of the returned list \texttt{.hasse} is as follows: \begin{itemize} \item The $i$\texttt{\symbol{45}}th entry contains a system of representatives for the $i-1$ dimensional faces of \mbox{\texttt{\mdseries\slshape poly}}. \item Each face is represented by a pair of lists \texttt{[vertices,boundary]}. The list of integers \texttt{vertices} represents the vertices of \mbox{\texttt{\mdseries\slshape poly}} which are contained in this face. The enumeration is chosen such that an \texttt{i} in the list represents the $i$\texttt{\symbol{45}}th entry of the list \texttt{Polymake(poly,"VERTICES");} \item The list \texttt{boundary} represents the boundary of the respective face. It is a list of pairs of integers \texttt{[j,g]}. The first entry lies between $-n$ and $n$, where $n$ is the number of faces of dimension $i-1$. This entry represents a face of dimension $i-1$ (or its additive inverse as a module generator). The second entry \texttt{g} is the position of the matrix in \texttt{.elts}. \end{itemize} This representation is compatible with the representation of free $\mathbb Z G$ modules in \textsf{Hap} and this method essentially calculates a free resolution of \mbox{\texttt{\mdseries\slshape group}}. If the value of \texttt{InfoHAPcryst} (\ref{InfoHAPcryst}) is 2 or more, additional information about the number of faces in every codimension, the number of orbits of the group on the free module generated by those faces, and the time it took to calculate the orbit decomposition is output. } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@SetInfoLevel(InfoHAPcryst,2);| !gapprompt@gap>| !gapinput@G:=SpaceGroup(3,165);| SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) !gapprompt@gap>| !gapinput@fd:=FundamentalDomainBieberbachGroup(G);| !gapprompt@gap>| !gapinput@fl:=FaceLatticeAndBoundaryBieberbachGroup(fd,G);;| #I 1(4/8): 0:00:00.004 #I 2(5/18): 0:00:00.000 #I 3(2/12): 0:00:00.000 #I Face lattice done ( 0:00:00.004). Calculating boundary #I done ( 0:00:00.004) Reformating... !gapprompt@gap>| !gapinput@RecNames(fl);| [ "hasse", "elts", "groupring" ] !gapprompt@gap>| !gapinput@fl.groupring;| \end{Verbatim} \subsection{\textcolor{Chapter }{ResolutionFromFLandBoundary}} \logpage{[ 4, 2, 3 ]}\nobreak \hyperdef{L}{X79A0B28A7FAE31B9}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ResolutionFromFLandBoundary({\mdseries\slshape fl, group})\index{ResolutionFromFLandBoundary@\texttt{ResolutionFromFLandBoundary}} \label{ResolutionFromFLandBoundary} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } Free resolution If \mbox{\texttt{\mdseries\slshape fl}} is the record output by \texttt{FaceLatticeAndBoundaryBieberbachGroup} (\ref{FaceLatticeAndBoundaryBieberbachGroup}) and \mbox{\texttt{\mdseries\slshape group}} is the corresponding group, this function returns a \texttt{HapResolution}. Of course, \mbox{\texttt{\mdseries\slshape fl}} has to be generated from a fundamental domain for \mbox{\texttt{\mdseries\slshape group}} } \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@G:=SpaceGroup(3,165);| SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) !gapprompt@gap>| !gapinput@fd:=FundamentalDomainBieberbachGroup(G);| !gapprompt@gap>| !gapinput@fl:=FaceLatticeAndBoundaryBieberbachGroup(fd,G);;| !gapprompt@gap>| !gapinput@ResolutionFromFLandBoundary(fl,G);| Resolution of length 3 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) . No contracting homotopy available. !gapprompt@gap>| !gapinput@ResolutionFromFLandBoundary(fl,G);| Resolution of length 3 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) . No contracting homotopy available. !gapprompt@gap>| !gapinput@List([0..4],Dimension(last));| [ 2, 5, 4, 1, 0 ] \end{Verbatim} } } \appendix \chapter{\textcolor{Chapter }{Resolutions in Hap}}\label{hapresolution} \logpage{[ "A", 0, 0 ]} \hyperdef{L}{X7C6DD73E7BB931AB}{} { This document is only concerned with the representation of resolutions in Hap. Note that it is not a part of Hap. The framework provided here is just an extension of Hap data types used in HAPcryst and HAPprime. From now on, let $G$ be a group and $\dots \to M_n\to M_{n-1}\to\dots\to M_1\to M_0\to Z$ be a resolution with free $ZG$ modules $M_i$. The elements of the modules $M_i$ can be represented in different ways. This is what makes different representations for resolutions desirable. First, we will look at the standard representation (\texttt{HapResolutionRep}) as it is defined in Hap. After that, we will present another representation for infinite groups. Note that all non\texttt{\symbol{45}}standard representations must be sub\texttt{\symbol{45}}representations of the standard representation to ensure compatibility with Hap. \section{\textcolor{Chapter }{The Standard Representation \texttt{HapResolutionRep}}}\label{hapresolutionrep} \logpage{[ "A", 1, 0 ]} \hyperdef{L}{X804F611B7E23BDB1}{} { For every $M_i$ we fix a basis and number its elements. Furthermore, it is assumed that we have a (partial) enumeration of the group of a resolution. In practice this is done by generating a lookup table on the fly. In standard representation, the elements of the modules $M_k$ are represented by lists \texttt{\symbol{45}}"words"\texttt{\symbol{45}} of pairs of integers. A letter \texttt{[i,g]} of such a word consists of the number of a basis element \texttt{i} or \texttt{\texttt{\symbol{45}}i} for its additive inverse and a number $g$ representing a group element. A \texttt{HapResolution} in \texttt{HapResolutionRep} representation is a component object with the components \begin{itemize} \item \texttt{group}, a group of arbitrary type. \item \texttt{elts}, a (partial) list of (possibly duplicate) elements in G. This list provides the "enumeration" of the group. Note that there are functions in Hap which assume that \texttt{elts[1]} is the identity element of G. \item \texttt{appendToElts(g)} a function that appends the group element \texttt{g} to \texttt{.elts}. This is not documented in Hap 1.8.6 but seems to be required for infinite groups. This requirement might vanish in some later version of Hap [G. Ellis, private communication]. \item \texttt{dimension(k)}, a function which returns the ZG\texttt{\symbol{45}}rank of the Module $M_k$ \item \texttt{boundary(k,j)}, a function which returns the image in $M_{k-1}$ of the $j$th free generator of $M_k$. Note that negative $j$ are valid as input as well. In this case the additive inverse of the boundary of the $j$th generator is returned \item \texttt{homotopy(k,[i,g])} a function which returns the image in $M_{k+1}$, under a contracting homotopy $M_k \to M_{k+1}$, of the element \texttt{[[i,g]]} in $M_k$. The value of this might be \texttt{fail}. However, currently (version 1.8.4) some Hap functions assume that \texttt{homotopy} is a function without testing. \item \texttt{properties}, a list of pairs \texttt{["name","value"]} "name" is a string and value is anything (boolean, number, string...). Every \texttt{HapResolution} (regardless of representation) has to have \texttt{["type","resolution"]}, \texttt{["length",length]} where \texttt{length} is the length of the resolution and \texttt{["characteristic",char]}. Currently (Hap 1.8.6), \texttt{length} must not be \texttt{infinity}. The values of these properties can be tested using the Hap function \texttt{EvaluateProperty(resolution,propertyname)}. \end{itemize} Note that making \texttt{HapResolution}s immutable will make the \texttt{.elts} component immutable. As this lookup table might change during calculations, we do not recommend using immutable resolutions (in any representation). } \section{\textcolor{Chapter }{The \texttt{HapLargeGroupResolutionRep} Representation}}\label{largegrouprep} \logpage{[ "A", 2, 0 ]} \hyperdef{L}{X8024014D8488FE30}{} { In this sub\texttt{\symbol{45}}representation of the standard representation, the module elements in this resolution are lists of groupring elements. So the lookup table \texttt{.elts} is not used as long as no conversion to standard representation takes place. In addition to the components of a \texttt{HapResolution}, a resolution in large group representation has the following components: \begin{itemize} \item \texttt{boundary2(resolution,term,gen)}, a function that returns the boundary of the \mbox{\texttt{\mdseries\slshape gen}}th generator of the \mbox{\texttt{\mdseries\slshape term}}th module. \item \texttt{groupring} the group ring of the resolution \mbox{\texttt{\mdseries\slshape resolution}}. \item \texttt{dimension2(resolution,term)} a function that returns the dimension of the \mbox{\texttt{\mdseries\slshape term}}th module of the resolution \mbox{\texttt{\mdseries\slshape resolution}}. \end{itemize} The effort of having two versions of \texttt{boundary} and \texttt{dimension} is necessary to keep the structure compatible with the usual Hap resolution. } } \chapter{\textcolor{Chapter }{Accessing and Manipulating Resolutions}}\logpage{[ "B", 0, 0 ]} \hyperdef{L}{X86374CEA7CDC6946}{} { \section{\textcolor{Chapter }{Representation\texttt{\symbol{45}}Independent Access Methods}}\logpage{[ "B", 1, 0 ]} \hyperdef{L}{X7A7225067E7895A9}{} { All methods listed below take a \texttt{HapResolution} in any representation. If the other arguments are compatible with the representation of the resolution, the returned value will be in the form defined by this representation. If the other arguments are in a different representation, \textsf{GAP}s method selection is used via \texttt{TryNextMethod()} to find an applicable method (a suitable representation). The idea behind this is that the results of computations have the same form as the input. And as all representations are sub\texttt{\symbol{45}}representations of the \texttt{HapResolutionRep} representation, input which is compatible with the \texttt{HapResolutionRep} representation is always valid. Every new representation must support the functions of this section. \subsection{\textcolor{Chapter }{StrongestValidRepresentationForLetter}} \logpage{[ "B", 1, 1 ]}\nobreak \hyperdef{L}{X7CBC6D4C783383BE}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{StrongestValidRepresentationForLetter({\mdseries\slshape resolution, term, letter})\index{StrongestValidRepresentationForLetter@\texttt{Strongest}\-\texttt{Valid}\-\texttt{Representation}\-\texttt{For}\-\texttt{Letter}} \label{StrongestValidRepresentationForLetter} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } filter Finds the sub\texttt{\symbol{45}}representation of \texttt{HapResolutionRep} for which \mbox{\texttt{\mdseries\slshape letter}} is a valid letter of the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resolution}}. Note that \mbox{\texttt{\mdseries\slshape resolution}} automatically is in some sub\texttt{\symbol{45}}representation of \texttt{HapResolutionRep}.This is mainly meant for debugging. } \subsection{\textcolor{Chapter }{StrongestValidRepresentationForWord}} \logpage{[ "B", 1, 2 ]}\nobreak \hyperdef{L}{X7C10841285614D04}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{StrongestValidRepresentationForWord({\mdseries\slshape resolution, term, word})\index{StrongestValidRepresentationForWord@\texttt{StrongestValidRepresentationForWord}} \label{StrongestValidRepresentationForWord} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } filter Finds the sub\texttt{\symbol{45}}representation of \texttt{HapResolutionRep} for which \mbox{\texttt{\mdseries\slshape word}} is a valid word of the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resolution}}. Note that \mbox{\texttt{\mdseries\slshape resolution}} automatically is in some sub\texttt{\symbol{45}}representation of \texttt{HapResolutionRep}. This is mainly meant for debugging. } \subsection{\textcolor{Chapter }{PositionInGroupOfResolution}} \logpage{[ "B", 1, 3 ]}\nobreak \hyperdef{L}{X780AD2DB7F5D4935}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{PositionInGroupOfResolution({\mdseries\slshape resolution, g})\index{PositionInGroupOfResolution@\texttt{PositionInGroupOfResolution}} \label{PositionInGroupOfResolution} }\hfill{\scriptsize (method)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{PositionInGroupOfResolutionNC({\mdseries\slshape resolution, g})\index{PositionInGroupOfResolutionNC@\texttt{PositionInGroupOfResolutionNC}} \label{PositionInGroupOfResolutionNC} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } positive integer This returns the position of the group element \mbox{\texttt{\mdseries\slshape g}} in the enumeration of the group of \mbox{\texttt{\mdseries\slshape resolution}}. The NC version does not check if \mbox{\texttt{\mdseries\slshape g}} really is an element of the group of \mbox{\texttt{\mdseries\slshape resolution}}. } \subsection{\textcolor{Chapter }{IsValidGroupInt}} \logpage{[ "B", 1, 4 ]}\nobreak \hyperdef{L}{X7A58EC7B8130D6E2}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsValidGroupInt({\mdseries\slshape resolution, n})\index{IsValidGroupInt@\texttt{IsValidGroupInt}} \label{IsValidGroupInt} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } boolean Returns true if the \mbox{\texttt{\mdseries\slshape n}}th element of the group of \mbox{\texttt{\mdseries\slshape resolution}} is known. } \subsection{\textcolor{Chapter }{GroupElementFromPosition}} \logpage{[ "B", 1, 5 ]}\nobreak \hyperdef{L}{X822604B67B2A9133}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{GroupElementFromPosition({\mdseries\slshape resolution, n})\index{GroupElementFromPosition@\texttt{GroupElementFromPosition}} \label{GroupElementFromPosition} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } group element or \texttt{fail} Returns \mbox{\texttt{\mdseries\slshape n}}th element of the group of \mbox{\texttt{\mdseries\slshape resolution}}. If the \mbox{\texttt{\mdseries\slshape n}}th element is not known, \texttt{fail} is returned. } \subsection{\textcolor{Chapter }{MultiplyGroupElts}} \logpage{[ "B", 1, 6 ]}\nobreak \hyperdef{L}{X7D3673E8840FA0B6}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{MultiplyGroupElts({\mdseries\slshape resolution, x, y})\index{MultiplyGroupElts@\texttt{MultiplyGroupElts}} \label{MultiplyGroupElts} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } positive integer or group element, depending on the type of \mbox{\texttt{\mdseries\slshape x}} and \mbox{\texttt{\mdseries\slshape y}} If \texttt{x} and \texttt{y} are given in standard representation (i.e. as integers), this returns the position of the product of the group elements represented by the positive integers \mbox{\texttt{\mdseries\slshape x}} and \mbox{\texttt{\mdseries\slshape x}}. If \texttt{x} and \texttt{y} are given in any other representation, the returned group element will also be represented in this way. } \subsection{\textcolor{Chapter }{MultiplyFreeZGLetterWithGroupElt}} \logpage{[ "B", 1, 7 ]}\nobreak \hyperdef{L}{X8540F3B37BAC695F}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{MultiplyFreeZGLetterWithGroupElt({\mdseries\slshape resolution, letter, g})\index{MultiplyFreeZGLetterWithGroupElt@\texttt{MultiplyFreeZGLetterWithGroupElt}} \label{MultiplyFreeZGLetterWithGroupElt} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } A letter Multiplies the letter \mbox{\texttt{\mdseries\slshape letter}} with the group element \mbox{\texttt{\mdseries\slshape g}} and returns the result. If \mbox{\texttt{\mdseries\slshape resolution}} is in standard representation, \mbox{\texttt{\mdseries\slshape g}} has to be an integer and \mbox{\texttt{\mdseries\slshape letter}} has to be a pair of integer. If \mbox{\texttt{\mdseries\slshape resolution}} is in any other representation, \mbox{\texttt{\mdseries\slshape letter}} and \mbox{\texttt{\mdseries\slshape g}} can be in a form compatible with that representation or in the standard form (in the latter case, the returned value will also have standard form). } \subsection{\textcolor{Chapter }{MultiplyFreeZGWordWithGroupElt}} \logpage{[ "B", 1, 8 ]}\nobreak \hyperdef{L}{X826835B185CA4DAF}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{MultiplyFreeZGWordWithGroupElt({\mdseries\slshape resolution, word, g})\index{MultiplyFreeZGWordWithGroupElt@\texttt{MultiplyFreeZGWordWithGroupElt}} \label{MultiplyFreeZGWordWithGroupElt} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } A word Multiplies the word \mbox{\texttt{\mdseries\slshape word}} with the group element \mbox{\texttt{\mdseries\slshape g}} and returns the result. If \mbox{\texttt{\mdseries\slshape resolution}} is in standard representation, \mbox{\texttt{\mdseries\slshape g}} has to be an integer and \mbox{\texttt{\mdseries\slshape word}} has to be a list of pairs of integers. If \mbox{\texttt{\mdseries\slshape resolution}} is in any other representation, \mbox{\texttt{\mdseries\slshape word}} and \mbox{\texttt{\mdseries\slshape g}} can be in a form compatible with that representation or in the standard form (in the latter case, the returned value will also have standard form). } \subsection{\textcolor{Chapter }{BoundaryOfFreeZGLetter}} \logpage{[ "B", 1, 9 ]}\nobreak \hyperdef{L}{X7D8B54D7828D7C5C}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BoundaryOfFreeZGLetter({\mdseries\slshape resolution, term, letter})\index{BoundaryOfFreeZGLetter@\texttt{BoundaryOfFreeZGLetter}} \label{BoundaryOfFreeZGLetter} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } free ZG word (in the same representation as \mbox{\texttt{\mdseries\slshape letter}}) Calculates the boundary of the letter (word of length 1) \mbox{\texttt{\mdseries\slshape letter}} of the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resolution}}. The returned value is a word of the \mbox{\texttt{\mdseries\slshape term}}\texttt{\symbol{45}}1st module and comes in the same representation as \mbox{\texttt{\mdseries\slshape letter}}. } \subsection{\textcolor{Chapter }{BoundaryOfFreeZGWord}} \logpage{[ "B", 1, 10 ]}\nobreak \hyperdef{L}{X81A6037F82C3C31E}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BoundaryOfFreeZGWord({\mdseries\slshape resolution, term, word})\index{BoundaryOfFreeZGWord@\texttt{BoundaryOfFreeZGWord}} \label{BoundaryOfFreeZGWord} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } free ZG word (in the same representation as \mbox{\texttt{\mdseries\slshape letter}}) Calculates the boundary of the word \mbox{\texttt{\mdseries\slshape word}} of the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resolution}}. The returned value is a word of the \mbox{\texttt{\mdseries\slshape term}}\texttt{\symbol{45}}1st module and comes in the same representation as \mbox{\texttt{\mdseries\slshape word}}. } } \section{\textcolor{Chapter }{Converting Between Representations}}\logpage{[ "B", 2, 0 ]} \hyperdef{L}{X7B94A2ED857C62D5}{} { Four methods are provided to convert letters and words from standard representation to any other representation and back again. \subsection{\textcolor{Chapter }{ConvertStandardLetter}} \logpage{[ "B", 2, 1 ]}\nobreak \hyperdef{L}{X7EB515317948BE8E}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ConvertStandardLetter({\mdseries\slshape resolution, term, letter})\index{ConvertStandardLetter@\texttt{ConvertStandardLetter}} \label{ConvertStandardLetter} }\hfill{\scriptsize (method)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ConvertStandardLetterNC({\mdseries\slshape resolution, term, letter})\index{ConvertStandardLetterNC@\texttt{ConvertStandardLetterNC}} \label{ConvertStandardLetterNC} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } letter in the representation of \mbox{\texttt{\mdseries\slshape resolution}} Converts the letter \mbox{\texttt{\mdseries\slshape letter}} in standard representation to the representation of \mbox{\texttt{\mdseries\slshape resolution}}. The NC version does not check whether \mbox{\texttt{\mdseries\slshape letter}} really is a letter in standard representation. } \subsection{\textcolor{Chapter }{ConvertStandardWord}} \logpage{[ "B", 2, 2 ]}\nobreak \hyperdef{L}{X7A1CB5DF7A459D76}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ConvertStandardWord({\mdseries\slshape resolution, term, word})\index{ConvertStandardWord@\texttt{ConvertStandardWord}} \label{ConvertStandardWord} }\hfill{\scriptsize (method)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ConvertStandardWordNC({\mdseries\slshape resolution, term, word})\index{ConvertStandardWordNC@\texttt{ConvertStandardWordNC}} \label{ConvertStandardWordNC} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } word in the representation of \mbox{\texttt{\mdseries\slshape resolution}} Converts the word \mbox{\texttt{\mdseries\slshape word}} in standard representation to the representation of \mbox{\texttt{\mdseries\slshape resolution}}. The NC version does not check whether \mbox{\texttt{\mdseries\slshape word}} is a valid word in standard representation. } \subsection{\textcolor{Chapter }{ConvertLetterToStandardRep}} \logpage{[ "B", 2, 3 ]}\nobreak \hyperdef{L}{X83153E2682184860}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ConvertLetterToStandardRep({\mdseries\slshape resolution, term, letter})\index{ConvertLetterToStandardRep@\texttt{ConvertLetterToStandardRep}} \label{ConvertLetterToStandardRep} }\hfill{\scriptsize (method)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ConvertLetterToStandardRepNC({\mdseries\slshape resolution, term, letter})\index{ConvertLetterToStandardRepNC@\texttt{ConvertLetterToStandardRepNC}} \label{ConvertLetterToStandardRepNC} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } letter in standard representation Converts the letter \mbox{\texttt{\mdseries\slshape letter}} in the representation of \mbox{\texttt{\mdseries\slshape resolution}} to the standard representation. The NC version does not check whether \mbox{\texttt{\mdseries\slshape letter}} is a valid letter of \mbox{\texttt{\mdseries\slshape resolution}}. } \subsection{\textcolor{Chapter }{ConvertWordToStandardRep}} \logpage{[ "B", 2, 4 ]}\nobreak \hyperdef{L}{X848203218271A166}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ConvertWordToStandardRep({\mdseries\slshape resolution, term, word})\index{ConvertWordToStandardRep@\texttt{ConvertWordToStandardRep}} \label{ConvertWordToStandardRep} }\hfill{\scriptsize (method)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ConvertWordToStandardRepNC({\mdseries\slshape resolution, term, word})\index{ConvertWordToStandardRepNC@\texttt{ConvertWordToStandardRepNC}} \label{ConvertWordToStandardRepNC} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } word in standard representation Converts the word \mbox{\texttt{\mdseries\slshape word}} in the representation of \mbox{\texttt{\mdseries\slshape resolution}} to the standard representation. The NC version does not check whether \mbox{\texttt{\mdseries\slshape word}} is a valid word of \mbox{\texttt{\mdseries\slshape resolution}}. } } \section{\textcolor{Chapter }{Special Methods for \texttt{HapResolutionRep}}}\logpage{[ "B", 3, 0 ]} \hyperdef{L}{X84FB45EB83B5822C}{} { Some methods explicitely require the input to be in the standard representation (\mbox{\texttt{\mdseries\slshape HapResolutionRep}}). Two of these test if a word/letter is really in standard representation, the other ones are non\texttt{\symbol{45}}check versions of the universal methods. \subsection{\textcolor{Chapter }{IsFreeZGLetter}} \logpage{[ "B", 3, 1 ]}\nobreak \hyperdef{L}{X7B803CC184BD2612}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsFreeZGLetter({\mdseries\slshape resolution, term, letter})\index{IsFreeZGLetter@\texttt{IsFreeZGLetter}} \label{IsFreeZGLetter} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } boolean Checks if \mbox{\texttt{\mdseries\slshape letter}} is an valid letter (word of length 1) in standard representation of the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resolution}}. } \subsection{\textcolor{Chapter }{IsFreeZGWord}} \logpage{[ "B", 3, 2 ]}\nobreak \hyperdef{L}{X7A36FB7B84E9A892}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsFreeZGWord({\mdseries\slshape resolution, term, word})\index{IsFreeZGWord@\texttt{IsFreeZGWord}} \label{IsFreeZGWord} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } boolean Check if \mbox{\texttt{\mdseries\slshape word}} is a valid word in large standard representation of the \mbox{\texttt{\mdseries\slshape term}}th module in \mbox{\texttt{\mdseries\slshape resolution}}. } \subsection{\textcolor{Chapter }{MultiplyGroupEltsNC}} \logpage{[ "B", 3, 3 ]}\nobreak \hyperdef{L}{X836D3F9886EED6AC}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{MultiplyGroupEltsNC({\mdseries\slshape resolution, x, y})\index{MultiplyGroupEltsNC@\texttt{MultiplyGroupEltsNC}} \label{MultiplyGroupEltsNC} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } positive integer Given positive integers \texttt{x} and \texttt{y}, this returns the position of the product of the group elements represented by the positive integers \mbox{\texttt{\mdseries\slshape x}} and \mbox{\texttt{\mdseries\slshape x}}. This assumes that all input is in standard representation and does not check the input. } \subsection{\textcolor{Chapter }{MultiplyFreeZGLetterWithGroupEltNC}} \logpage{[ "B", 3, 4 ]}\nobreak \hyperdef{L}{X85893CC5823508A8}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{MultiplyFreeZGLetterWithGroupEltNC({\mdseries\slshape resolution, letter, g})\index{MultiplyFreeZGLetterWithGroupEltNC@\texttt{MultiplyFreeZGLetterWithGroupEltNC}} \label{MultiplyFreeZGLetterWithGroupEltNC} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } A letter in standard representation Multiplies the letter \mbox{\texttt{\mdseries\slshape letter}} with the group element represented by the positive integer \mbox{\texttt{\mdseries\slshape g}} and returns the result. The input is assumed to be in \mbox{\texttt{\mdseries\slshape HapResolutionRep}} and is not checked. } \subsection{\textcolor{Chapter }{MultiplyFreeZGWordWithGroupEltNC}} \logpage{[ "B", 3, 5 ]}\nobreak \hyperdef{L}{X8073DE7E7AD8B7CB}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{MultiplyFreeZGWordWithGroupEltNC({\mdseries\slshape resolution, word, g})\index{MultiplyFreeZGWordWithGroupEltNC@\texttt{MultiplyFreeZGWordWithGroupEltNC}} \label{MultiplyFreeZGWordWithGroupEltNC} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } A letter in standard representation Multiplies the word \mbox{\texttt{\mdseries\slshape word}} with the group element represented by the positive integer \mbox{\texttt{\mdseries\slshape g}} and returns the result. The input is assumed to be in \mbox{\texttt{\mdseries\slshape HapResolutionRep}} and is not checked. } \subsection{\textcolor{Chapter }{BoundaryOfFreeZGLetterNC}} \logpage{[ "B", 3, 6 ]}\nobreak \hyperdef{L}{X7BD3994E7C414149}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BoundaryOfFreeZGLetterNC({\mdseries\slshape resolution, term, letter})\index{BoundaryOfFreeZGLetterNC@\texttt{BoundaryOfFreeZGLetterNC}} \label{BoundaryOfFreeZGLetterNC} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } free ZG word in standard representation Calculates the boundary of the letter (word of length 1) \mbox{\texttt{\mdseries\slshape letter}} of the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resolution}}. The input is assumed to be in standard representation and not checked. } \subsection{\textcolor{Chapter }{BoundaryOfFreeZGWordNC}} \logpage{[ "B", 3, 7 ]}\nobreak \hyperdef{L}{X84B1DA21805A0880}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BoundaryOfFreeZGWordNC({\mdseries\slshape resolution, term, word})\index{BoundaryOfFreeZGWordNC@\texttt{BoundaryOfFreeZGWordNC}} \label{BoundaryOfFreeZGWordNC} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } free ZG word in standard representation Calculates the boundary of the word \mbox{\texttt{\mdseries\slshape word}} of the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resolution}}. The input is assumed to be in standard representation and not checked. } } \section{\textcolor{Chapter }{The \texttt{HapLargeGroupResolutionRep} Representation}}\logpage{[ "B", 4, 0 ]} \hyperdef{L}{X8024014D8488FE30}{} { The large group representation has one additional component called \texttt{groupring}. Elements of the modules in a resolution are represented by lists of group ring elements. The length of the list corresponds to the dimension of the free module. All methods for the generic representation do also work for the large group representation. Some of them are wrappers for special methods which do only work for this representation. The following list only contains the methods which are not already present in the generic representation. Note that the input or the output of these functions does not comply with the standard representation. \subsection{\textcolor{Chapter }{GroupRingOfResolution}} \logpage{[ "B", 4, 1 ]}\nobreak \hyperdef{L}{X861BE6C787FA8032}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{GroupRingOfResolution({\mdseries\slshape resolution})\index{GroupRingOfResolution@\texttt{GroupRingOfResolution}} \label{GroupRingOfResolution} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } group ring This returns the group ring of \mbox{\texttt{\mdseries\slshape resolution}}. Note that by the way that group rings are handled in \textsf{GAP}, this is not equal to \texttt{GroupRing(R,GroupOfResolution(\mbox{\texttt{\mdseries\slshape resolution}}))} where \texttt{R} is the ring of the resolution. } \subsection{\textcolor{Chapter }{MultiplyGroupElts{\textunderscore}LargeGroupRep}} \logpage{[ "B", 4, 2 ]}\nobreak \hyperdef{L}{X8338F7A37F240E33}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{MultiplyGroupElts{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, x, y})\index{MultiplyGroupElts{\textunderscore}LargeGroupRep@\texttt{Multiply}\-\texttt{Group}\-\texttt{Elts{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{MultiplyGroupEltsuScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{MultiplyGroupEltsNC{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, x, y})\index{MultiplyGroupEltsNC{\textunderscore}LargeGroupRep@\texttt{Multiply}\-\texttt{Group}\-\texttt{Elts}\-\texttt{N}\-\texttt{C{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{MultiplyGroupEltsNCuScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } group element Returns the product of \mbox{\texttt{\mdseries\slshape x}} and \mbox{\texttt{\mdseries\slshape y}}. The NC version does not check whether \mbox{\texttt{\mdseries\slshape x}} and \mbox{\texttt{\mdseries\slshape y}} are actually elements of the group of \mbox{\texttt{\mdseries\slshape resolution}}. } \subsection{\textcolor{Chapter }{IsFreeZGLetterNoTermCheck{\textunderscore}LargeGroupRep}} \logpage{[ "B", 4, 3 ]}\nobreak \hyperdef{L}{X86F91A948022DEBB}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsFreeZGLetterNoTermCheck{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, letter})\index{IsFreeZGLetterNoTermCheck{\textunderscore}LargeGroupRep@\texttt{IsFree}\-\texttt{Z}\-\texttt{G}\-\texttt{Letter}\-\texttt{No}\-\texttt{Term}\-\texttt{Check{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{IsFreeZGLetterNoTermCheckuScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } boolean Returns \texttt{true} if \mbox{\texttt{\mdseries\slshape letter}} has the form of a letter (a module element with exactly one non\texttt{\symbol{45}}zero entry which has exactly one non\texttt{\symbol{45}}zero coefficient) a module of \mbox{\texttt{\mdseries\slshape resolution}} in the \texttt{HapLargeGroupResolution} representation. Note that it is not tested if \mbox{\texttt{\mdseries\slshape letter}} actually is a letter in any term of \mbox{\texttt{\mdseries\slshape resolution}} } \subsection{\textcolor{Chapter }{IsFreeZGWordNoTermCheck{\textunderscore}LargeGroupRep}} \logpage{[ "B", 4, 4 ]}\nobreak \hyperdef{L}{X793BA61478AEBE16}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsFreeZGWordNoTermCheck{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, word})\index{IsFreeZGWordNoTermCheck{\textunderscore}LargeGroupRep@\texttt{IsFree}\-\texttt{Z}\-\texttt{G}\-\texttt{Word}\-\texttt{No}\-\texttt{Term}\-\texttt{Check{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{IsFreeZGWordNoTermCheckuScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } boolean Returns \texttt{true} if \mbox{\texttt{\mdseries\slshape word}} has the form of a word of a module of \mbox{\texttt{\mdseries\slshape resolution}} in the \texttt{HapLargeGroupResolution} representation. Note that it is not tested if \mbox{\texttt{\mdseries\slshape word}} actually is a word in any term of \mbox{\texttt{\mdseries\slshape resolution}}. } \subsection{\textcolor{Chapter }{IsFreeZGLetter{\textunderscore}LargeGroupRep}} \logpage{[ "B", 4, 5 ]}\nobreak \hyperdef{L}{X85A7BFC284E9D9CB}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsFreeZGLetter{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, term, letter})\index{IsFreeZGLetter{\textunderscore}LargeGroupRep@\texttt{IsFree}\-\texttt{Z}\-\texttt{G}\-\texttt{Letter{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{IsFreeZGLetteruScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } boolean Returns \texttt{true} if and only if \mbox{\texttt{\mdseries\slshape letter}} is a letter (a word of length 1) of the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resolution}} in the \texttt{hapLargeGroupResolution} representation. I.e. it tests if \mbox{\texttt{\mdseries\slshape letter}} is a module element with exactly one non\texttt{\symbol{45}}zero entry which has exactly one non\texttt{\symbol{45}}zero coefficient. } \subsection{\textcolor{Chapter }{IsFreeZGWord{\textunderscore}LargeGroupRep}} \logpage{[ "B", 4, 6 ]}\nobreak \hyperdef{L}{X7BF4A7EC83BE61C8}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsFreeZGWord{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, term, word})\index{IsFreeZGWord{\textunderscore}LargeGroupRep@\texttt{IsFree}\-\texttt{Z}\-\texttt{G}\-\texttt{Word{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{IsFreeZGWorduScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } boolean Tests if \mbox{\texttt{\mdseries\slshape word}} is an element of the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resoultion}}. } \subsection{\textcolor{Chapter }{MultiplyFreeZGLetterWithGroupElt{\textunderscore}LargeGroupRep}} \logpage{[ "B", 4, 7 ]}\nobreak \hyperdef{L}{X7A4B682079630694}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{MultiplyFreeZGLetterWithGroupElt{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, letter, g})\index{MultiplyFreeZGLetterWithGroupElt{\textunderscore}LargeGroupRep@\texttt{Multiply}\-\texttt{Free}\-\texttt{Z}\-\texttt{G}\-\texttt{Letter}\-\texttt{With}\-\texttt{Group}\-\texttt{Elt{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{MultiplyFreeZGLetterWithGroupEltuScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{MultiplyFreeZGLetterWithGroupEltNC{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, letter, g})\index{MultiplyFreeZGLetterWithGroupEltNC{\textunderscore}LargeGroupRep@\texttt{Multiply}\-\texttt{Free}\-\texttt{Z}\-\texttt{G}\-\texttt{Letter}\-\texttt{With}\-\texttt{Group}\-\texttt{Elt}\-\texttt{N}\-\texttt{C{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{MultiplyFreeZGLetterWithGroupEltNCuScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } free ZG letter in large group representation Multiplies the letter \mbox{\texttt{\mdseries\slshape letter}} with the group element \mbox{\texttt{\mdseries\slshape g}} and returns the result. The NC version does not check whether \mbox{\texttt{\mdseries\slshape g}} is an element of the group of \mbox{\texttt{\mdseries\slshape resolution}} and \mbox{\texttt{\mdseries\slshape letter}} can be a letter. } \subsection{\textcolor{Chapter }{MultiplyFreeZGWordWithGroupElt{\textunderscore}LargeGroupRep}} \logpage{[ "B", 4, 8 ]}\nobreak \hyperdef{L}{X7F2365D2851E3E3C}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{MultiplyFreeZGWordWithGroupElt{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, word, g})\index{MultiplyFreeZGWordWithGroupElt{\textunderscore}LargeGroupRep@\texttt{Multiply}\-\texttt{Free}\-\texttt{Z}\-\texttt{G}\-\texttt{Word}\-\texttt{With}\-\texttt{Group}\-\texttt{Elt{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{MultiplyFreeZGWordWithGroupEltuScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{MultiplyFreeZGWordWithGroupEltNC{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, word, g})\index{MultiplyFreeZGWordWithGroupEltNC{\textunderscore}LargeGroupRep@\texttt{Multiply}\-\texttt{Free}\-\texttt{Z}\-\texttt{G}\-\texttt{Word}\-\texttt{With}\-\texttt{Group}\-\texttt{Elt}\-\texttt{N}\-\texttt{C{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{MultiplyFreeZGWordWithGroupEltNCuScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } free ZG word in large group representation Multiplies the word \mbox{\texttt{\mdseries\slshape word}} with the group element \mbox{\texttt{\mdseries\slshape g}} and returns the result. The NC version does not check whether \mbox{\texttt{\mdseries\slshape g}} is an element of the group of \mbox{\texttt{\mdseries\slshape resolution}} and \mbox{\texttt{\mdseries\slshape word}} can be a word. } \subsection{\textcolor{Chapter }{GeneratorsOfModuleOfResolution{\textunderscore}LargeGroupRep}} \logpage{[ "B", 4, 9 ]}\nobreak \hyperdef{L}{X8355F6E8842B3D8C}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{GeneratorsOfModuleOfResolution{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, term})\index{GeneratorsOfModuleOfResolution{\textunderscore}LargeGroupRep@\texttt{Generators}\-\texttt{Of}\-\texttt{Module}\-\texttt{Of}\-\texttt{Resolution{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{GeneratorsOfModuleOfResolutionuScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } list of letters/words in large group representation Returns a set of generators for the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resolution}}. The returned value is a list of vectors of group ring elements. } \subsection{\textcolor{Chapter }{BoundaryOfGenerator{\textunderscore}LargeGroupRep}} \logpage{[ "B", 4, 10 ]}\nobreak \hyperdef{L}{X840DF79086D5473E}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BoundaryOfGenerator{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, term, n})\index{BoundaryOfGenerator{\textunderscore}LargeGroupRep@\texttt{Boundary}\-\texttt{Of}\-\texttt{Generator{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{BoundaryOfGeneratoruScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BoundaryOfGeneratorNC{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, term, n})\index{BoundaryOfGeneratorNC{\textunderscore}LargeGroupRep@\texttt{Boundary}\-\texttt{Of}\-\texttt{Generator}\-\texttt{N}\-\texttt{C{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{BoundaryOfGeneratorNCuScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } free ZG word in the large group representation Returns the boundary of the \mbox{\texttt{\mdseries\slshape n}}th generator of the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resolution}} as a word in the \mbox{\texttt{\mdseries\slshape n\texttt{\symbol{45}}1}}st module (in large group representation). The NC version does not check whether there is a \mbox{\texttt{\mdseries\slshape term}}th module and if it has at least \mbox{\texttt{\mdseries\slshape n}} generators. } \subsection{\textcolor{Chapter }{BoundaryOfFreeZGLetterNC{\textunderscore}LargeGroupRep}} \logpage{[ "B", 4, 11 ]}\nobreak \hyperdef{L}{X83D90EC28357DCCE}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BoundaryOfFreeZGLetterNC{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, term, letter})\index{BoundaryOfFreeZGLetterNC{\textunderscore}LargeGroupRep@\texttt{Boundary}\-\texttt{Of}\-\texttt{Free}\-\texttt{Z}\-\texttt{G}\-\texttt{Letter}\-\texttt{N}\-\texttt{C{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{BoundaryOfFreeZGLetterNCuScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BoundaryOfFreeZGLetter{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, term, letter})\index{BoundaryOfFreeZGLetter{\textunderscore}LargeGroupRep@\texttt{Boundary}\-\texttt{Of}\-\texttt{Free}\-\texttt{Z}\-\texttt{G}\-\texttt{Letter{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{BoundaryOfFreeZGLetteruScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } free ZG word in large group representation Calculates the boundary of the letter \mbox{\texttt{\mdseries\slshape letter}} of the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resolution}} in large group representation. The NC version does not check whether \mbox{\texttt{\mdseries\slshape letter}} actually is a letter in the \mbox{\texttt{\mdseries\slshape term}}th module. } \subsection{\textcolor{Chapter }{BoundaryOfFreeZGWord{\textunderscore}LargeGroupRep}} \logpage{[ "B", 4, 12 ]}\nobreak \hyperdef{L}{X78C681D37F8DC2A1}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BoundaryOfFreeZGWord{\textunderscore}LargeGroupRep({\mdseries\slshape resolution, term, word})\index{BoundaryOfFreeZGWord{\textunderscore}LargeGroupRep@\texttt{Boundary}\-\texttt{Of}\-\texttt{Free}\-\texttt{Z}\-\texttt{G}\-\texttt{Word{\textunderscore}}\-\texttt{Large}\-\texttt{GroupRep}} \label{BoundaryOfFreeZGWorduScoreLargeGroupRep} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } free ZG word in large group representation Calculates the boundary of the element \mbox{\texttt{\mdseries\slshape word}} of the \mbox{\texttt{\mdseries\slshape term}}th module of \mbox{\texttt{\mdseries\slshape resolution}} in large group representation. The NC version does not check whether \mbox{\texttt{\mdseries\slshape word}} actually is a word in the \mbox{\texttt{\mdseries\slshape term}}th module. } } } \chapter{\textcolor{Chapter }{Contracting Homotopies}}\logpage{[ "C", 0, 0 ]} \hyperdef{L}{X792B9CC97C670AEA}{} { \section{\textcolor{Chapter }{The \texttt{PartialContractingHomotopy} Data Type}}\logpage{[ "C", 1, 0 ]} \hyperdef{L}{X7E957D2381DBE362}{} { A partial contracting homotopy is a component object that knows the values of a contracting homotopy on some subspace of a resolution. It has two mandatory components: \begin{itemize} \item \texttt{.resolution} a \texttt{HapResolution} on which the contraction is defined. \item \texttt{.knownPartOfHomotopy} a list of \texttt{Record}s with components \texttt{.space} and \texttt{.map}. \end{itemize} Let \texttt{h} be a contracting homotopy. The lookup table \texttt{.knownPartOfHomotopy} has one entry for each term of the resolution \texttt{h.resolution} (that is, one more than \texttt{Length(h.resolution)}). The $i$ th element of \texttt{.knownPartOfHomotopy} contains a record with components \texttt{.space} and \texttt{.map} where \texttt{.space} is a \texttt{FreeZGWord} of the $i-1$ st term of the resolution. The component \texttt{.map} is a list of length \texttt{Dimension(h.resolution)(i\texttt{\symbol{45}}1)}. The entries of this list are pairs \texttt{[g,im]} where \texttt{g} represents a group element and \texttt{im} represents the image of the contraction. So the entry \texttt{[g,im]} in the \texttt{k}th component of the list \texttt{.map} means that the \texttt{k}th free generator of the corresponding module multiplied with the group element represented by \texttt{g} is mapped to \texttt{im} under the partial contracting homotopy. Note that the data type of \texttt{g} or \texttt{im} are not fixed at this level. They must be specified by the sub representations. Also, \texttt{im} need not represent the actual image under a contracting homotopy. It is possible to just store a bit of information that is then used to generate the actual image. As this is a very general data type, it has very few methods. \subsection{\textcolor{Chapter }{ResolutionOfContractingHomotopy}} \logpage{[ "C", 1, 1 ]}\nobreak \hyperdef{L}{X7D899ACD7EB512FA}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ResolutionOfContractingHomotopy({\mdseries\slshape homotopy})\index{ResolutionOfContractingHomotopy@\texttt{ResolutionOfContractingHomotopy}} \label{ResolutionOfContractingHomotopy} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } A \texttt{HapResolution} This returns the resolution of the homotopy \mbox{\texttt{\mdseries\slshape homotopy}} (the component \mbox{\texttt{\mdseries\slshape homotopy!.resolution}}). } \subsection{\textcolor{Chapter }{PartialContractingHomotopyLookup}} \logpage{[ "C", 1, 2 ]}\nobreak \hyperdef{L}{X79C69C9B877C6D60}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{PartialContractingHomotopyLookup({\mdseries\slshape homotopy, term, generator, groupel})\index{PartialContractingHomotopyLookup@\texttt{PartialContractingHomotopyLookup}} \label{PartialContractingHomotopyLookup} }\hfill{\scriptsize (method)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{PartialContractingHomotopyLookupNC({\mdseries\slshape homotopy, term, generator, groupel})\index{PartialContractingHomotopyLookupNC@\texttt{PartialContractingHomotopyLookupNC}} \label{PartialContractingHomotopyLookupNC} }\hfill{\scriptsize (method)}}\\ \textbf{\indent Returns:\ } The entry \texttt{im} of the corresponding lookup table Looks up the known part of the contracting homotopy \mbox{\texttt{\mdseries\slshape homotopy}} and returns the corresponding image. More precisely, it returns the image of the \mbox{\texttt{\mdseries\slshape generator}}th generator times the group element represented by \mbox{\texttt{\mdseries\slshape groupel}} in term \mbox{\texttt{\mdseries\slshape term}} under the partial homotopy. The data type of this image depends on the representation of \mbox{\texttt{\mdseries\slshape homotopy}}. \mbox{\texttt{\mdseries\slshape term}} has to be an integer and \mbox{\texttt{\mdseries\slshape generator}} a positive integer. \mbox{\texttt{\mdseries\slshape groupel}} only has to be an \texttt{Object}. The NC version does not do any checks on the input. The other version checks if \mbox{\texttt{\mdseries\slshape term}} and \mbox{\texttt{\mdseries\slshape generator}} are sensible. It does not check \mbox{\texttt{\mdseries\slshape groupel}}. } } } \def\bibname{References\logpage{[ "Bib", 0, 0 ]} \hyperdef{L}{X7A6F98FD85F02BFE}{} } \bibliographystyle{alpha} \bibliography{HAPcryst} \addcontentsline{toc}{chapter}{References} \def\indexname{Index\logpage{[ "Ind", 0, 0 ]} \hyperdef{L}{X83A0356F839C696F}{} } \cleardoublepage \phantomsection \addcontentsline{toc}{chapter}{Index} \printindex \immediate\write\pagenrlog{["Ind", 0, 0], \arabic{page},} \newpage \immediate\write\pagenrlog{["End"], \arabic{page}];} \immediate\closeout\pagenrlog \end{document} hapcryst-0.2.0/doc/chap1_mj.html0000644000175100017510000002316515160525022016076 0ustar runnerrunner GAP (HAPcryst) - Chapter 1: Introduction
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

1 Introduction

1.1 Abstract and Notation

HAPcryst is an extension for "Homological Algebra Programming" (HAP, [Ell]) by Graham Ellis. It uses geometric methods to calculate resolutions for crystallographic groups. In this manual, we will use the terms "space group" and "crystallographic group" synonymous. As usual in GAP, group elements are supposed to act from the right. To emphasize this fact, some functions have names ending in "OnRight" (namely those, which rely on the action from the right). This is also meant to make work with HAPcryst and cryst [EGN] easier.

The functions called "somethingStandardSpaceGroup" are supposed to work for standard crystallographic groups on left and right some time in the future. Currently only the versions acting on right are implemented. As in cryst [EGN], space groups are represented as affine linear groups. For the computations in HAPcryst, crystallographic groups have to be in "standard form". That is, the translation basis has to be the standard basis of the space. This implies that the linear part of a group element need not be orthogonal with respect to the usual scalar product.

1.1-1 The natural action of crystallographic groups

There is some confusion about the way crystallographic groups are written. This concerns the question if we act on left or on right and if vectors are of the form [1,...] or [...,1].

As mentioned, HAPcryst handles affine crystallographic groups on right (and maybe later also on left) acting on vectors of the form \([...,1]\).

BUT: The functions in HAPcryst do not take augmented vectors as input (no leading or ending ones). The handling of vectors is done internally. So in HAPcryst, a crystallographic group is a group of \(n\times n\) matrices which acts on a vector space of dimension \(n-1\) whose elements are vectors of length \(n-1\) (not \(n\)). Example:

gap> G:=SpaceGroup(3,4); #This group acts on 3-Space
SpaceGroupOnRightBBNWZ( 3, 2, 1, 1, 2 )
gap> Display(Representative(G));
[ [  1,  0,  0,  0 ],
  [  0,  1,  0,  0 ],
  [  0,  0,  1,  0 ],
  [  0,  0,  0,  1 ] ]
gap> OrbitStabilizerInUnitCubeOnRight(G,[1/2,0,0]);
rec( orbit := [ [ 1/2, 0, 0 ], [ 1/2, 1/2, 0 ] ],
  stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ],
          [ 0, 0, 0, 1 ] ] ]) )

1.2 Requirements

The following GAP packages are required

  • polymaking which in turn depends on the computational geometry software polymake.

  • HAP

  • Cryst

The following GAP packages are not required but highly recommended:

  • carat

  • CrystCat

  • GAPDoc is needed to display the online manual

1.2-1 Recommendation concerning polymake

Calculating resolutions of Bieberbach groups involves convex hull computations. polymake by default uses cdd to compute convex hulls. Experiments suggest that lrs is the more suitable algorithm for the computations done in HAPcryst than the default cdd. You can change the behaviour of by editing the file "yourhomedirectory/.polymake/prefer.pl". It should contain a section like this (just make sure lrs is before cdd, the position of beneath_beyond does not matter):

#########################################
application polytope;

prefer "*.convex_hull  lrs, beneath_beyond, cdd";

1.3 Global Variables

HAPcryst itself does only have one global variable, namely InfoHAPcryst (1.3-1). The location of files generated for interaction with polymake are determined by the value of POLYMAKE_DATA_DIR (polymaking: POLYMAKE_DATA_DIR) which is a global variable of polymaking.

1.3-1 InfoHAPcryst
‣ InfoHAPcryst( info class )

At a level of 1, only the most important messages are printed. At level 2, additional information is displayed, and level 3 is even more verbose. At level 0, HAPcryst remains silent.

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/chap3.html0000644000175100017510000005050615160525022015411 0ustar runnerrunner GAP (HAPcryst) - Chapter 3: Algorithms of Orbit-Stabilizer Type
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

3 Algorithms of Orbit-Stabilizer Type

We introduce a way to calculate a sufficient part of an orbit and the stabilizer of a point.

3.1 Orbit Stabilizer for Crystallographic Groups

3.1-1 OrbitStabilizerInUnitCubeOnRight
‣ OrbitStabilizerInUnitCubeOnRight( group, x )( method )

Returns: A record containing

  • .stabilizer: the stabilizer of x.

  • .orbit set of vectors from [0,1)^n which represents the orbit.

Let x be a rational vector from [0,1)^n and group a space group in standard form. The function then calculates the part of the orbit which lies inside the cube [0,1)^n and the stabilizer of x. Observe that every element of the full orbit differs from a point in the returned orbit only by a pure translation.

Note that the restriction to points from [0,1)^n makes sense if orbits should be compared and the vector passed to OrbitStabilizerInUnitCubeOnRight should be an element of the returned orbit (part).

gap> S:=SpaceGroup(3,5);;
gap> OrbitStabilizerInUnitCubeOnRight(S,[1/2,0,9/11]);   
rec( orbit := [ [ 0, 1/2, 2/11 ], [ 1/2, 0, 9/11 ] ], 
  stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], 
          [ 0, 0, 0, 1 ] ] ]) )
gap> OrbitStabilizerInUnitCubeOnRight(S,[0,0,0]);     
rec( orbit := [ [ 0, 0, 0 ] ], stabilizer := <matrix group with 2 generators> )

If you are interested in other parts of the orbit, you can use VectorModOne (2.1-2) for the base point and the functions ShiftedOrbitPart (3.1-9), TranslationsToOneCubeAroundCenter (3.1-10) and TranslationsToBox (3.1-11) for the resulting orbit
Suppose we want to calculate the part of the orbit of [4/3,5/3,7/3] in the cube of sidelength 1 around this point:

gap> S:=SpaceGroup(3,5);;
gap> p:=[4/3,5/3,7/3];;
gap> o:=OrbitStabilizerInUnitCubeOnRight(S,VectorModOne(p)).orbit;
[ [ 1/3, 2/3, 1/3 ], [ 1/3, 2/3, 2/3 ] ]
gap> box:=p+[[-1,1],[-1,1],[-1,1]];
[ [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ] ]
gap> o2:=Concatenation(List(o,i->i+TranslationsToBox(i,box)));;
gap> # This is what we looked for. But it is somewhat large:
gap> Size(o2);
54

3.1-2 OrbitStabilizerInUnitCubeOnRightOnSets
‣ OrbitStabilizerInUnitCubeOnRightOnSets( group, set )( method )

Returns: A record containing

  • .stabilizer: the stabilizer of set.

  • .orbit set of sets of vectors from [0,1)^n which represents the orbit.

Calculates orbit and stabilizer of a set of vectors. Just as OrbitStabilizerInUnitCubeOnRight (3.1-1), it needs input from [0,1)^n. The returned orbit part .orbit is a set of sets such that every element of .orbit has a non-trivial intersection with the cube [0,1)^n. In general, these sets will not lie inside [0,1)^n completely.

gap> S:=SpaceGroup(3,5);;
gap> OrbitStabilizerInUnitCubeOnRightOnSets(S,[[0,0,0],[0,1/2,0]]);
rec( orbit := [ [ [ -1/2, 0, 0 ], [ 0, 0, 0 ] ], 
                [ [ 0, 0, 0 ], [ 0, 1/2, 0 ] ],
                [ [ 1/2, 0, 0 ], [ 1, 0, 0 ] ] ],
  stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], 
                        [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ]) )

3.1-3 OrbitPartInVertexSetsStandardSpaceGroup
‣ OrbitPartInVertexSetsStandardSpaceGroup( group, vertexset, allvertices )( method )

Returns: Set of subsets of allvertices.

If allvertices is a set of vectors and vertexset is a subset thereof, then OrbitPartInVertexSetsStandardSpaceGroup returns that part of the orbit of vertexset which consists entirely of subsets of allvertices. Note that,unlike the other OrbitStabilizer algorithms, this does not require the input to lie in some particular part of the space.

gap> S:=SpaceGroup(3,5);;
gap> OrbitPartInVertexSetsStandardSpaceGroup(S,[[0,1,5],[1,2,0]],
> Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]]));
[ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 2, 6 ], [ 2, 3, 1 ] ] ]
gap> OrbitPartInVertexSetsStandardSpaceGroup(S, [[1,2,0]],
> Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]]));
[ [ [ 0, 1, 5 ] ], [ [ 1, 1, 0 ] ], [ [ 1, 2, 0 ] ], [ [ 1, 2, 6 ] ], [ [ 2, 3, 1 ] ] ]

3.1-4 OrbitPartInFacesStandardSpaceGroup
‣ OrbitPartInFacesStandardSpaceGroup( group, vertexset, faceset )( method )

Returns: Set of subsets of faceset.

This calculates the orbit of a space group on sets restricted to a set of faces.
If faceset is a set of sets of vectors and vertexset is an element of faceset, then OrbitPartInFacesStandardSpaceGroup returns that part of the orbit of vertexset which consists entirely of elements of faceset.
Note that,unlike the other OrbitStabilizer algorithms, this does not require the input to lie in some particular part of the space.

3.1-5 OrbitPartAndRepresentativesInFacesStandardSpaceGroup
‣ OrbitPartAndRepresentativesInFacesStandardSpaceGroup( group, vertexset, faceset )( method )

Returns: A set of face-matrix pairs .

This is a slight variation of OrbitPartInFacesStandardSpaceGroup (3.1-4) that also returns a representative for every orbit element.

gap> S:=SpaceGroup(3,5);;
gap> OrbitPartInVertexSetsStandardSpaceGroup(S,[[0,1,5],[1,2,0]],
> Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]]));
[ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 2, 6 ], [ 2, 3, 1 ] ] ]
gap> OrbitPartInFacesStandardSpaceGroup(S,[[0,1,5],[1,2,0]],
> Set( [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [[1/17,6,1/2],[1,2,7]]]));
[ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ] ]
gap> OrbitPartAndRepresentativesInFacesStandardSpaceGroup(S,[[0,1,5],[1,2,0]],
> Set( [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [[1/17,6,1/2],[1,2,7]]]));
[ [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ],
      [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ] ]

3.1-6 StabilizerOnSetsStandardSpaceGroup
‣ StabilizerOnSetsStandardSpaceGroup( group, set )( method )

Returns: finite group of affine matrices (OnRight)

Given a set set of vectors and a space group group in standard form, this method calculates the stabilizer of that set in the full crystallographic group.

 
gap> G:=SpaceGroup(3,12);;
gap> v:=[ 0, 0,0 ];;
gap> s:=StabilizerOnSetsStandardSpaceGroup(G,[v]);
<matrix group with 2 generators>
gap> s2:=OrbitStabilizerInUnitCubeOnRight(G,v).stabilizer;
<matrix group with 2 generators>
gap> s2=s;
true

3.1-7 RepresentativeActionOnRightOnSets
‣ RepresentativeActionOnRightOnSets( group, set, imageset )( method )

Returns: Affine matrix.

Returns an element of the space group S which takes the set set to the set imageset. The group must be in standard form and act on the right.

gap> S:=SpaceGroup(3,5);;
gap> RepresentativeActionOnRightOnSets(G, [[0,0,0],[0,1/2,0]],
>        [ [ 0, 1/2, 0 ], [ 0, 1, 0 ] ]);
[ [ 0, -1, 0, 0 ], [ -1, 0, 0, 0 ], [ 0, 0, -1, 0 ], [ 0, 1, 0, 1 ] ]

3.1-8 Getting other orbit parts

HAPcryst does not calculate the full orbit but only the part of it having coefficients between -1/2 and 1/2. The other parts of the orbit can be calculated using the following functions.

3.1-9 ShiftedOrbitPart
‣ ShiftedOrbitPart( point, orbitpart )( method )

Returns: Set of vectors

Takes each vector in orbitpart to the cube unit cube centered in point.

gap> ShiftedOrbitPart([0,0,0],[[1/2,1/2,1/3],-[1/2,1/2,1/2],[19,3,1]]);
[ [ 1/2, 1/2, 1/3 ], [ 1/2, 1/2, 1/2 ], [ 0, 0, 0 ] ]
gap> ShiftedOrbitPart([1,1,1],[[1/2,1/2,1/2],-[1/2,1/2,1/2]]);
[ [ 3/2, 3/2, 3/2 ] ]

3.1-10 TranslationsToOneCubeAroundCenter
‣ TranslationsToOneCubeAroundCenter( point, center )( method )

Returns: List of integer vectors

This method returns the list of all integer vectors which translate point into the box center+[-1/2,1/2]^n

gap> TranslationsToOneCubeAroundCenter([1/2,1/2,1/3],[0,0,0]);
[ [ 0, 0, 0 ], [ 0, -1, 0 ], [ -1, 0, 0 ], [ -1, -1, 0 ] ]
gap> TranslationsToOneCubeAroundCenter([1,0,1],[0,0,0]);
[ [ -1, 0, -1 ] ]

3.1-11 TranslationsToBox
‣ TranslationsToBox( point, box )( method )

Returns: List of integer vectors or the empty list

Given a vector v and a list of pairs, this function returns the translation vectors (integer vectors) which take v into the box box. The box box has to be given as a list of pairs.

gap> TranslationsToBox([0,0],[[1/2,2/3],[1/2,2/3]]);
[  ]
gap> TranslationsToBox([0,0],[[-3/2,1/2],[1,4/3]]);
[ [ -1, 1 ], [ 0, 1 ] ]
gap> TranslationsToBox([0,0],[[-3/2,1/2],[2,1]]);
Error, Box must not be empty
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/chap0_mj.html0000644000175100017510000004562615160525022016103 0ustar runnerrunner GAP (HAPcryst) - Contents
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

HAPcryst

A HAP extension for crystallographic groups

Version 0.2.0

24 March 2026

Marc Roeder
Email: roeder.marc@gmail.com

Copyright

© 2007 Marc Röder.

This package is distributed under the terms of the GNU General Public License version 2 or later (at your convenience). See the file LICENSE or https://www.gnu.org/copyleft/gpl.html

Acknowledgements

This work was supported by Marie Curie Grant No. MTKD-CT-2006-042685

Contents

B Accessing and Manipulating Resolutions

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/fundamentaldomain.xml0000644000175100017510000001630115160525022017730 0ustar runnerrunner
Fundamental Domains Let S be a crystallographic group. A Fundamental domain is a closed convex set containing a system of representatives for the Orbits of S in its natural action on euclidian space.
There are two algorithms for calculating fundamental domains in HAPcryst. One uses the geometry and relies on having the standard rule for evaluating the scalar product (i.e. the gramian matrix is the identity). The other one is independent of the gramian matrix but does only work for Bieberbach groups, while the first ("geometric") algorithm works for arbitrary crystallographic groups given a point with trivial stabilizer. a PolymakeObject Let G be an AffineCrystGroupOnRight and v a vector. A fundamental domain containing v is calculated and returned as a PolymakeObject. The vector v is used as the starting point for a Dirichlet-Voronoi construction. If no v is given, the origin is used as starting point if it has trivial stabiliser. Otherwise an error is cast.
fd:=FundamentalDomainStandardSpaceGroup([1/2,0,1/5],SpaceGroup(3,9)); gap> Polymake(fd,"N_VERTICES"); 24 gap> fd:=FundamentalDomainStandardSpaceGroup(SpaceGroup(3,9)); gap> Polymake(fd,"N_VERTICES"); 8 ]]> a PolymakeObject Given a starting vector v and a Bieberbach group G in standard form, this method calculates the Dirichlet domain with respect to v. If gram is not supplied, the average gramian matrix is used (see ). It is not tested if gram is symmetric and positive definite. It is also not tested, if the product defined by gram is invariant under the point group of G.

The behaviour of this function is influenced by the option ineqThreshold

If the value of is 2 or more, for each approximation the number of vertices of the approximation, the number of vertices that have to be considered during the calculation, the number of facets, and new inequalities is shown.

Note that the algorithm chooses vertices in random order and also writes inequalities for polymake in random order. a0:=[[ 1, 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0, 0 ], > [ 0, 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 0 ], > [ 0, 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, -1, -1, 0 ], > [ -1/2, 0, 0, 1/6, 0, 0, 1 ] > ];; gap> a1:=[[ 0, -1, 0, 0, 0, 0, 0 ],[ 0, 0, -1, 0, 0, 0, 0 ], > [ 1, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 0 ], > [ 0, 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 1, 0 ], > [ 0, 0, 0, 0, 1/3, -1/3, 1 ] > ];; gap> trans:=List(Group((1,2,3,4,5,6)),g-> > TranslationOnRightFromVector(Permuted([1,0,0,0,0,0],g)));; gap> S:=AffineCrystGroupOnRight(Concatenation(trans,[a0,a1])); gap> SetInfoLevel(InfoHAPcryst,2); gap> FundamentalDomainBieberbachGroup(S:ineqThreshold:=10); #I v: 104/104 f:15 #I new: 201 #I v: 961/961 f:58 #I new: 20 #I v: 1143/805 f:69 #I new: 12 #I v: 1059/555 f:64 #I new: 15 #I v: 328/109 f:33 #I new: 12 #I v: 336/58 f:32 #I new: 0 gap> FundamentalDomainBieberbachGroup(S:ineqThreshold:=1000); #I v: 104/104 f:15 #I new: 149 #I v: 635/635 f:41 #I new: 115 #I v: 336/183 f:32 #I new: 0 #I out of inequalities ]]> a PolymakeObject This uses an alternative algorithm based on geometric considerations. It is not used in any of the high-level methods. Let v be a vector and orbit a sufficiently large part of the orbit of v under a crystallographic group with standard- orthogonal point group (satisfying A^t=A^-1). A geometric algorithm is then used to calculate the Dirichlet domain with respect to v. This also works for crystallographic groups which are not Bieberbach. The point v has to have trivial stabilizer.
The intersection of the full orbit with the unit cube around v is sufficiently large.
G:=SpaceGroup(3,9);; gap> v:=[0,0,0]; [ 0, 0, 0 ] gap> orbit:=OrbitStabilizerInUnitCubeOnRight(G,v).orbit; [ [ 0, 0, 0 ], [ 0, 0, 1/2 ] ] gap> fd:=FundamentalDomainFromGeneralPointAndOrbitPartGeometric(v,orbit); gap> Polymake(fd,"N_VERTICES"); 8 ]]> true or false This tests if a PolymakeObject poly is a fundamental domain for the affine crystallographic group G in standard form.
The function tests the following: First, does the orbit of any vertex of poly have a point inside poly (if this is the case, false is returned). Second: Is every facet of poly the image of a different facet under a group element which does not fix poly. If this is satisfied, true is returned.
true, false or fail This tests if a PolymakeObject poly is a fundamental domain for the affine crystallographic group G in standard form and if this group is torsion free (ie a Bieberbach group)
It returns true if G is torsion free and poly is a fundamental domain for G. If poly is not a fundamental domain, false is returned regardless of the structure of G. And if G is not torsion free, the method returns fail. If G is polycyclic, torsion freeness is tested using a representation as pcp group. Otherwise the stabilisers of the faces of the fundamental domain poly are calculated (G is torsion free if and only if it all these stabilisers are trivial).

hapcryst-0.2.0/doc/chapC_mj.html0000644000175100017510000001741115160525022016115 0ustar runnerrunner GAP (HAPcryst) - Appendix C: Contracting Homotopies
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

C Contracting Homotopies

C.1 The PartialContractingHomotopy Data Type

A partial contracting homotopy is a component object that knows the values of a contracting homotopy on some subspace of a resolution. It has two mandatory components:

  • .resolution a HapResolution on which the contraction is defined.

  • .knownPartOfHomotopy a list of Records with components .space and .map.

Let h be a contracting homotopy. The lookup table .knownPartOfHomotopy has one entry for each term of the resolution h.resolution (that is, one more than Length(h.resolution)).

The \(i\) th element of .knownPartOfHomotopy contains a record with components .space and .map where .space is a FreeZGWord of the \(i-1\) st term of the resolution. The component .map is a list of length Dimension(h.resolution)(i-1). The entries of this list are pairs [g,im] where g represents a group element and im represents the image of the contraction. So the entry [g,im] in the kth component of the list .map means that the kth free generator of the corresponding module multiplied with the group element represented by g is mapped to im under the partial contracting homotopy. Note that the data type of g or im are not fixed at this level. They must be specified by the sub representations. Also, im need not represent the actual image under a contracting homotopy. It is possible to just store a bit of information that is then used to generate the actual image.

As this is a very general data type, it has very few methods.

C.1-1 ResolutionOfContractingHomotopy
‣ ResolutionOfContractingHomotopy( homotopy )( method )

Returns: A HapResolution

This returns the resolution of the homotopy homotopy (the component homotopy!.resolution).

C.1-2 PartialContractingHomotopyLookup
‣ PartialContractingHomotopyLookup( homotopy, term, generator, groupel )( method )
‣ PartialContractingHomotopyLookupNC( homotopy, term, generator, groupel )( method )

Returns: The entry im of the corresponding lookup table

Looks up the known part of the contracting homotopy homotopy and returns the corresponding image. More precisely, it returns the image of the generatorth generator times the group element represented by groupel in term term under the partial homotopy. The data type of this image depends on the representation of homotopy.

term has to be an integer and generator a positive integer. groupel only has to be an Object.

The NC version does not do any checks on the input. The other version checks if term and generator are sensible. It does not check groupel.

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/times.css0000644000175100017510000000026115160525022015351 0ustar runnerrunner/* times.css Frank LĂ¼beck */ /* Change default CSS to use Times font. */ body { font-family: Times,Times New Roman,serif; } hapcryst-0.2.0/doc/chap2.html0000644000175100017510000004421015160525022015403 0ustar runnerrunner GAP (HAPcryst) - Chapter 2: Bits and Pieces
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

2 Bits and Pieces

This chapter contains a few very basic functions which are needed for space group calculations and were missing in standard GAP.

2.1 Matrices and Vectors

2.1-1 SignRat
‣ SignRat( x )( method )

Returns: sign of the rational number x (Standard GAP currently only has SignInt).

2.1-2 VectorModOne
‣ VectorModOne( v )( method )

Returns: Rational vector of the same length with enties in [0,1)

For a rational vector v, this returns the vector with all entries taken "mod 1".

gap> SignRat((-4)/(-2));
1
gap> SignRat(9/(-2));
-1
gap> VectorModOne([1/10,100/9,5/6,6/5]);
[ 1/10, 1/9, 5/6, 1/5 ]

2.1-3 IsSquareMat
‣ IsSquareMat( matrix )( method )

Returns: true if matrix is a square matrix and false otherwise.

2.1-4 DimensionSquareMat
‣ DimensionSquareMat( matrix )( method )

Returns: Number of lines in the matrix matrix if it is square and fail otherwise

gap> m:=[[1,2,3],[4,5,6],[9,6,12]];
[ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 9, 6, 12 ] ]
gap> IsSquareMat(m);
true
gap> DimensionSquareMat(m);
3
gap> DimensionSquareMat([[1,2],[1,2,3]]);
fail

Affine mappings of n dimensional space are often written as a pair (A,v) where A is a linear mapping and v is a vector. GAP represents affine mappings by n+1 times n+1 matrices M which satisfy M_{n+1,n+1}=1 and M_{i,n+1}=0 for all 1≤ i ≤ n.

An affine matrix acts on an n dimensional space which is written as a space of n+1 tuples with n+1st entry 1. Here we give two functions to handle these affine matrices.

2.2 Affine Matrices OnRight

2.2-1 LinearPartOfAffineMatOnRight
‣ LinearPartOfAffineMatOnRight( mat )( method )

Returns: the linear part of the affine matrix mat. That is, everything except for the last row and column.

2.2-2 BasisChangeAffineMatOnRight
‣ BasisChangeAffineMatOnRight( transform, mat )( method )

Returns: affine matrix with same dimensions as mat

A basis change transform of an n dimensional space induces a transformation on affine mappings on this space. If mat is a affine matrix (in particular, it is (n+1)Ă— (n+1)), this method returns the image of mat under the basis transformation induced by transform.

gap> c:=[[0,1],[1,0]];
[ [ 0, 1 ], [ 1, 0 ] ]
gap> m:=[[1/2,0,0],[0,2/3,0],[1,0,1]];
[ [ 1/2, 0, 0 ], [ 0, 2/3, 0 ], [ 1, 0, 1 ] ]
gap> BasisChangeAffineMatOnRight(c,m);
[ [ 2/3, 0, 0 ], [ 0, 1/2, 0 ], [ 0, 1, 1 ] ]

2.2-3 TranslationOnRightFromVector
‣ TranslationOnRightFromVector( v )( method )

Returns: Affine matrix

Given a vector v with n entries, this method returns a (n+1)Ă— (n+1) matrix which corresponds to the affine translation defined by v.

gap> m:=TranslationOnRightFromVector([1,2,3]);;
gap> Display(m);
[ [  1,  0,  0,  0 ],
  [  0,  1,  0,  0 ],
  [  0,  0,  1,  0 ],
  [  1,  2,  3,  1 ] ]
gap> LinearPartOfAffineMatOnRight(m);
[ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ]
gap> BasisChangeAffineMatOnRight([[3,2,1],[0,1,0],[0,0,1]],m);
[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 3, 4, 4, 1 ] ]

2.3 Geometry

2.3-1 GramianOfAverageScalarProductFromFiniteMatrixGroup
‣ GramianOfAverageScalarProductFromFiniteMatrixGroup( G )( method )

Returns: Symmetric positive definite matrix

For a finite matrix group G, the gramian matrix of the average scalar product is returned. This is the sum over all gg^t with g∈ G (actually it is enough to take a generating set). The group G is orthogonal with respect to the scalar product induced by the returned matrix.

2.3-2 Inequalities

Inequalities are represented in the same way they are represented in polymaking. The vector (v_0,...,v_n) represents the inequality 0≤ v_0+v_1 x_1+... + v_n x_n.

2.3-3 BisectorInequalityFromPointPair
‣ BisectorInequalityFromPointPair( v1, v2[, gram] )( method )

Returns: vector of length Length(v1)+1

Calculates the inequality defining the half-space containing v1 such that v1-v2 is perpendicular on the bounding hyperplane. And (v1-v2)/2 is contained in the bounding hyperplane.
If the matrix gram is given, it is used as the gramian matrix. Otherwiese, the standard scalar product is used. It is not checked if gram is positive definite or symmetric.

2.3-4 WhichSideOfHyperplane
‣ WhichSideOfHyperplane( v, ineq )( method )
‣ WhichSideOfHyperplaneNC( v, ineq )( method )

Returns: -1 (below) 0 (in) or 1 (above).

Let v be a vector of length n and ineq an inequality represented by a vector of length n+1. Then WhichSideOfHyperplane(v, ineq) returns 1 if v is a solution of the inequality but not the equation given by ineq, it returns 0 if v is a solution to the equation and -1 if it is not a solution of the inequality ineq.

The NC version does not test the input for correctness.

gap> BisectorInequalityFromPointPair([0,0],[1,0]);
[ 1, -2, 0 ]
gap> ineq:=BisectorInequalityFromPointPair([0,0],[1,0],[[5,4],[4,5]]);
[ 5, -10, -8 ]
gap> ineq{[2,3]}*[1/2,0];
-5
gap> WhichSideOfHyperplane([0,0],ineq);
1
gap> WhichSideOfHyperplane([1/2,0],ineq);
0

2.3-5 RelativePositionPointAndPolygon
‣ RelativePositionPointAndPolygon( point, poly )( operation )

Returns: one of "VERTEX", "FACET", "OUTSIDE", "INSIDE"

Let poly be a PolymakeObject and point a vector. If point is a vertex of poly, the string "VERTEX" is returned. If point lies inside poly, "INSIDE" is returned and if it lies in a facet, "FACET" is returned and if point does not lie inside poly, the function returns "OUTSIDE".

2.4 Space Groups

2.4-1 PointGroupRepresentatives
‣ PointGroupRepresentatives( group )( attribute )

Returns: list of matrices

Given an AffineCrystGroupOnLeftOrRight group, this returns a list of representatives of the point group of group. That is, a system of representatives for the factor group modulo translations. This is an attribute of AffineCrystGroupOnLeftOrRight

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/hasse.xml0000644000175100017510000000047415160525022015351 0ustar runnerrunner
Generating (parts of) the Hasse diagram To generate a resolution of a crystallographic group, we don't necessarily need the full Hasse diagram of a corresponding fundamental domain. Here are a few functions which can be used to calculate a (sufficient) part of it. blabla...
hapcryst-0.2.0/doc/chapC.txt0000644000175100017510000000731715160525022015306 0ustar runnerrunner C Contracting Homotopies C.1 The PartialContractingHomotopy Data Type A partial contracting homotopy is a component object that knows the values of a contracting homotopy on some subspace of a resolution. It has two mandatory components:  .resolution a HapResolution on which the contraction is defined.  .knownPartOfHomotopy a list of Records with components .space and .map. Let h be a contracting homotopy. The lookup table .knownPartOfHomotopy has one entry for each term of the resolution h.resolution (that is, one more than Length(h.resolution)). The i th element of .knownPartOfHomotopy contains a record with components .space and .map where .space is a FreeZGWord of the i-1 st term of the resolution. The component .map is a list of length Dimension(h.resolution)(i-1). The entries of this list are pairs [g,im] where g represents a group element and im represents the image of the contraction. So the entry [g,im] in the kth component of the list .map means that the kth free generator of the corresponding module multiplied with the group element represented by g is mapped to im under the partial contracting homotopy. Note that the data type of g or im are not fixed at this level. They must be specified by the sub representations. Also, im need not represent the actual image under a contracting homotopy. It is possible to just store a bit of information that is then used to generate the actual image. As this is a very general data type, it has very few methods. C.1-1 ResolutionOfContractingHomotopy ResolutionOfContractingHomotopy( homotopy )  method Returns: A HapResolution This returns the resolution of the homotopy homotopy (the component homotopy!.resolution). C.1-2 PartialContractingHomotopyLookup PartialContractingHomotopyLookup( homotopy, term, generator, groupel )  method PartialContractingHomotopyLookupNC( homotopy, term, generator, groupel )  method Returns: The entry im of the corresponding lookup table Looks up the known part of the contracting homotopy homotopy and returns the corresponding image. More precisely, it returns the image of the generatorth generator times the group element represented by groupel in term term under the partial homotopy. The data type of this image depends on the representation of homotopy. term has to be an integer and generator a positive integer. groupel only has to be an Object. The NC version does not do any checks on the input. The other version checks if term and generator are sensible. It does not check groupel. hapcryst-0.2.0/doc/toggless.js0000644000175100017510000000420515160525022015705 0ustar runnerrunner/* toggless.js Frank LĂ¼beck */ /* this file contains two functions: mergeSideTOCHooks: this changes div.ContSect elements to the class ContSectClosed and includes a hook to toggle between ContSectClosed and ContSectOpen. openclosetoc: this function does the toggling, the rest is done by CSS */ closedTOCMarker = "â–¶ "; openTOCMarker = "â–¼ "; noTOCMarker = " "; /* merge hooks into side toc for opening/closing subsections with openclosetoc */ function mergeSideTOCHooks() { var hlist = document.getElementsByTagName("div"); for (var i = 0; i < hlist.length; i++) { if (hlist[i].className == "ContSect") { var chlds = hlist[i].childNodes; var el = document.createElement("span"); var oncl = document.createAttribute("class"); oncl.nodeValue = "toctoggle"; el.setAttributeNode(oncl); var cont; if (chlds.length > 2) { var oncl = document.createAttribute("onclick"); oncl.nodeValue = "openclosetoc(event)"; el.setAttributeNode(oncl); cont = document.createTextNode(closedTOCMarker); } else { cont = document.createTextNode(noTOCMarker); } el.appendChild(cont); hlist[i].firstChild.insertBefore(el, hlist[i].firstChild.firstChild); hlist[i].className = "ContSectClosed"; } } } function openclosetoc (event) { /* first two steps to make it work in most browsers */ var evt=window.event || event; if (!evt.target) evt.target=evt.srcElement; var markClosed = document.createTextNode(closedTOCMarker); var markOpen = document.createTextNode(openTOCMarker); var par = evt.target.parentNode.parentNode; if (par.className == "ContSectOpen") { par.className = "ContSectClosed"; evt.target.replaceChild(markClosed, evt.target.firstChild); } else if (par.className == "ContSectClosed") { par.className = "ContSectOpen"; evt.target.replaceChild(markOpen, evt.target.firstChild); } } /* adjust jscontent which is called onload */ jscontentfuncs.push(mergeSideTOCHooks); hapcryst-0.2.0/doc/ragged.css0000644000175100017510000000023115160525022015456 0ustar runnerrunner/* times.css Frank LĂ¼beck */ /* Change default CSS to use Times font. */ body { text-align: left; } hapcryst-0.2.0/doc/chapBib.txt0000644000175100017510000000047215160525022015613 0ustar runnerrunner References [EGN] Eick, B., Gahler, F. and Nickel, W., cryst, {https://www.gap-system.org/Packages/cryst.html}. [Ell] Ellis, G., HAP, {http://hamilton.nuigalway.ie/Hap/www/}.  hapcryst-0.2.0/doc/chapB.txt0000644000175100017510000005143615160525022015306 0ustar runnerrunner B Accessing and Manipulating Resolutions B.1 Representation-Independent Access Methods All methods listed below take a HapResolution in any representation. If the other arguments are compatible with the representation of the resolution, the returned value will be in the form defined by this representation. If the other arguments are in a different representation, GAPs method selection is used via TryNextMethod() to find an applicable method (a suitable representation). The idea behind this is that the results of computations have the same form as the input. And as all representations are sub-representations of the HapResolutionRep representation, input which is compatible with the HapResolutionRep representation is always valid. Every new representation must support the functions of this section. B.1-1 StrongestValidRepresentationForLetter StrongestValidRepresentationForLetter( resolution, term, letter )  method Returns: filter Finds the sub-representation of HapResolutionRep for which letter is a valid letter of the termth module of resolution. Note that resolution automatically is in some sub-representation of HapResolutionRep.This is mainly meant for debugging. B.1-2 StrongestValidRepresentationForWord StrongestValidRepresentationForWord( resolution, term, word )  method Returns: filter Finds the sub-representation of HapResolutionRep for which word is a valid word of the termth module of resolution. Note that resolution automatically is in some sub-representation of HapResolutionRep. This is mainly meant for debugging. B.1-3 PositionInGroupOfResolution PositionInGroupOfResolution( resolution, g )  method PositionInGroupOfResolutionNC( resolution, g )  method Returns: positive integer This returns the position of the group element g in the enumeration of the group of resolution. The NC version does not check if g really is an element of the group of resolution. B.1-4 IsValidGroupInt IsValidGroupInt( resolution, n )  method Returns: boolean Returns true if the nth element of the group of resolution is known. B.1-5 GroupElementFromPosition GroupElementFromPosition( resolution, n )  method Returns: group element or fail Returns nth element of the group of resolution. If the nth element is not known, fail is returned. B.1-6 MultiplyGroupElts MultiplyGroupElts( resolution, x, y )  method Returns: positive integer or group element, depending on the type of x and y If x and y are given in standard representation (i.e. as integers), this returns the position of the product of the group elements represented by the positive integers x and x. If x and y are given in any other representation, the returned group element will also be represented in this way. B.1-7 MultiplyFreeZGLetterWithGroupElt MultiplyFreeZGLetterWithGroupElt( resolution, letter, g )  method Returns: A letter Multiplies the letter letter with the group element g and returns the result. If resolution is in standard representation, g has to be an integer and letter has to be a pair of integer. If resolution is in any other representation, letter and g can be in a form compatible with that representation or in the standard form (in the latter case, the returned value will also have standard form). B.1-8 MultiplyFreeZGWordWithGroupElt MultiplyFreeZGWordWithGroupElt( resolution, word, g )  method Returns: A word Multiplies the word word with the group element g and returns the result. If resolution is in standard representation, g has to be an integer and word has to be a list of pairs of integers. If resolution is in any other representation, word and g can be in a form compatible with that representation or in the standard form (in the latter case, the returned value will also have standard form). B.1-9 BoundaryOfFreeZGLetter BoundaryOfFreeZGLetter( resolution, term, letter )  method Returns: free ZG word (in the same representation as letter) Calculates the boundary of the letter (word of length 1) letter of the termth module of resolution. The returned value is a word of the term-1st module and comes in the same representation as letter. B.1-10 BoundaryOfFreeZGWord BoundaryOfFreeZGWord( resolution, term, word )  method Returns: free ZG word (in the same representation as letter) Calculates the boundary of the word word of the termth module of resolution. The returned value is a word of the term-1st module and comes in the same representation as word. B.2 Converting Between Representations Four methods are provided to convert letters and words from standard representation to any other representation and back again. B.2-1 ConvertStandardLetter ConvertStandardLetter( resolution, term, letter )  method ConvertStandardLetterNC( resolution, term, letter )  method Returns: letter in the representation of resolution Converts the letter letter in standard representation to the representation of resolution. The NC version does not check whether letter really is a letter in standard representation. B.2-2 ConvertStandardWord ConvertStandardWord( resolution, term, word )  method ConvertStandardWordNC( resolution, term, word )  method Returns: word in the representation of resolution Converts the word word in standard representation to the representation of resolution. The NC version does not check whether word is a valid word in standard representation. B.2-3 ConvertLetterToStandardRep ConvertLetterToStandardRep( resolution, term, letter )  method ConvertLetterToStandardRepNC( resolution, term, letter )  method Returns: letter in standard representation Converts the letter letter in the representation of resolution to the standard representation. The NC version does not check whether letter is a valid letter of resolution. B.2-4 ConvertWordToStandardRep ConvertWordToStandardRep( resolution, term, word )  method ConvertWordToStandardRepNC( resolution, term, word )  method Returns: word in standard representation Converts the word word in the representation of resolution to the standard representation. The NC version does not check whether word is a valid word of resolution. B.3 Special Methods for HapResolutionRep Some methods explicitely require the input to be in the standard representation (HapResolutionRep). Two of these test if a word/letter is really in standard representation, the other ones are non-check versions of the universal methods. B.3-1 IsFreeZGLetter IsFreeZGLetter( resolution, term, letter )  method Returns: boolean Checks if letter is an valid letter (word of length 1) in standard representation of the termth module of resolution. B.3-2 IsFreeZGWord IsFreeZGWord( resolution, term, word )  method Returns: boolean Check if word is a valid word in large standard representation of the termth module in resolution. B.3-3 MultiplyGroupEltsNC MultiplyGroupEltsNC( resolution, x, y )  method Returns: positive integer Given positive integers x and y, this returns the position of the product of the group elements represented by the positive integers x and x. This assumes that all input is in standard representation and does not check the input. B.3-4 MultiplyFreeZGLetterWithGroupEltNC MultiplyFreeZGLetterWithGroupEltNC( resolution, letter, g )  method Returns: A letter in standard representation Multiplies the letter letter with the group element represented by the positive integer g and returns the result. The input is assumed to be in HapResolutionRep and is not checked. B.3-5 MultiplyFreeZGWordWithGroupEltNC MultiplyFreeZGWordWithGroupEltNC( resolution, word, g )  method Returns: A letter in standard representation Multiplies the word word with the group element represented by the positive integer g and returns the result. The input is assumed to be in HapResolutionRep and is not checked. B.3-6 BoundaryOfFreeZGLetterNC BoundaryOfFreeZGLetterNC( resolution, term, letter )  method Returns: free ZG word in standard representation Calculates the boundary of the letter (word of length 1) letter of the termth module of resolution. The input is assumed to be in standard representation and not checked. B.3-7 BoundaryOfFreeZGWordNC BoundaryOfFreeZGWordNC( resolution, term, word )  method Returns: free ZG word in standard representation Calculates the boundary of the word word of the termth module of resolution. The input is assumed to be in standard representation and not checked. B.4 The HapLargeGroupResolutionRep Representation The large group representation has one additional component called groupring. Elements of the modules in a resolution are represented by lists of group ring elements. The length of the list corresponds to the dimension of the free module. All methods for the generic representation do also work for the large group representation. Some of them are wrappers for special methods which do only work for this representation. The following list only contains the methods which are not already present in the generic representation. Note that the input or the output of these functions does not comply with the standard representation. B.4-1 GroupRingOfResolution GroupRingOfResolution( resolution )  method Returns: group ring This returns the group ring of resolution. Note that by the way that group rings are handled in GAP, this is not equal to GroupRing(R,GroupOfResolution(resolution)) where R is the ring of the resolution. B.4-2 MultiplyGroupElts_LargeGroupRep MultiplyGroupElts_LargeGroupRep( resolution, x, y )  method MultiplyGroupEltsNC_LargeGroupRep( resolution, x, y )  method Returns: group element Returns the product of x and y. The NC version does not check whether x and y are actually elements of the group of resolution. B.4-3 IsFreeZGLetterNoTermCheck_LargeGroupRep IsFreeZGLetterNoTermCheck_LargeGroupRep( resolution, letter )  method Returns: boolean Returns true if letter has the form of a letter (a module element with exactly one non-zero entry which has exactly one non-zero coefficient) a module of resolution in the HapLargeGroupResolution representation. Note that it is not tested if letter actually is a letter in any term of resolution B.4-4 IsFreeZGWordNoTermCheck_LargeGroupRep IsFreeZGWordNoTermCheck_LargeGroupRep( resolution, word )  method Returns: boolean Returns true if word has the form of a word of a module of resolution in the HapLargeGroupResolution representation. Note that it is not tested if word actually is a word in any term of resolution. B.4-5 IsFreeZGLetter_LargeGroupRep IsFreeZGLetter_LargeGroupRep( resolution, term, letter )  method Returns: boolean Returns true if and only if letter is a letter (a word of length 1) of the termth module of resolution in the hapLargeGroupResolution representation. I.e. it tests if letter is a module element with exactly one non-zero entry which has exactly one non-zero coefficient. B.4-6 IsFreeZGWord_LargeGroupRep IsFreeZGWord_LargeGroupRep( resolution, term, word )  method Returns: boolean Tests if word is an element of the termth module of resoultion. B.4-7 MultiplyFreeZGLetterWithGroupElt_LargeGroupRep MultiplyFreeZGLetterWithGroupElt_LargeGroupRep( resolution, letter, g )  method MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep( resolution, letter, g )  method Returns: free ZG letter in large group representation Multiplies the letter letter with the group element g and returns the result. The NC version does not check whether g is an element of the group of resolution and letter can be a letter. B.4-8 MultiplyFreeZGWordWithGroupElt_LargeGroupRep MultiplyFreeZGWordWithGroupElt_LargeGroupRep( resolution, word, g )  method MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep( resolution, word, g )  method Returns: free ZG word in large group representation Multiplies the word word with the group element g and returns the result. The NC version does not check whether g is an element of the group of resolution and word can be a word. B.4-9 GeneratorsOfModuleOfResolution_LargeGroupRep GeneratorsOfModuleOfResolution_LargeGroupRep( resolution, term )  method Returns: list of letters/words in large group representation Returns a set of generators for the termth module of resolution. The returned value is a list of vectors of group ring elements. B.4-10 BoundaryOfGenerator_LargeGroupRep BoundaryOfGenerator_LargeGroupRep( resolution, term, n )  method BoundaryOfGeneratorNC_LargeGroupRep( resolution, term, n )  method Returns: free ZG word in the large group representation Returns the boundary of the nth generator of the termth module of resolution as a word in the n-1st module (in large group representation). The NC version does not check whether there is a termth module and if it has at least n generators. B.4-11 BoundaryOfFreeZGLetterNC_LargeGroupRep BoundaryOfFreeZGLetterNC_LargeGroupRep( resolution, term, letter )  method BoundaryOfFreeZGLetter_LargeGroupRep( resolution, term, letter )  method Returns: free ZG word in large group representation Calculates the boundary of the letter letter of the termth module of resolution in large group representation. The NC version does not check whether letter actually is a letter in the termth module. B.4-12 BoundaryOfFreeZGWord_LargeGroupRep BoundaryOfFreeZGWord_LargeGroupRep( resolution, term, word )  method Returns: free ZG word in large group representation Calculates the boundary of the element word of the termth module of resolution in large group representation. The NC version does not check whether word actually is a word in the termth module. hapcryst-0.2.0/doc/chap0.html0000644000175100017510000004465115160525022015412 0ustar runnerrunner GAP (HAPcryst) - Contents
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

HAPcryst

A HAP extension for crystallographic groups

Version 0.2.0

24 March 2026

Marc Roeder
Email: roeder.marc@gmail.com

Copyright

© 2007 Marc Röder.

This package is distributed under the terms of the GNU General Public License version 2 or later (at your convenience). See the file LICENSE or https://www.gnu.org/copyleft/gpl.html

Acknowledgements

This work was supported by Marie Curie Grant No. MTKD-CT-2006-042685

Contents

B Accessing and Manipulating Resolutions

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/chap4.html0000644000175100017510000005712015160525022015411 0ustar runnerrunner GAP (HAPcryst) - Chapter 4: Resolutions of Crystallographic Groups
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

4 Resolutions of Crystallographic Groups

4.1 Fundamental Domains

Let S be a crystallographic group. A Fundamental domain is a closed convex set containing a system of representatives for the Orbits of S in its natural action on euclidian space.
There are two algorithms for calculating fundamental domains in HAPcryst. One uses the geometry and relies on having the standard rule for evaluating the scalar product (i.e. the gramian matrix is the identity). The other one is independent of the gramian matrix but does only work for Bieberbach groups, while the first ("geometric") algorithm works for arbitrary crystallographic groups given a point with trivial stabilizer.

4.1-1 FundamentalDomainStandardSpaceGroup
‣ FundamentalDomainStandardSpaceGroup( [v, ]G )( operation )

Returns: a PolymakeObject

Let G be an AffineCrystGroupOnRight and v a vector. A fundamental domain containing v is calculated and returned as a PolymakeObject. The vector v is used as the starting point for a Dirichlet-Voronoi construction. If no v is given, the origin is used as starting point if it has trivial stabiliser. Otherwise an error is cast.

gap> fd:=FundamentalDomainStandardSpaceGroup([1/2,0,1/5],SpaceGroup(3,9));
<polymake object>
gap> Polymake(fd,"N_VERTICES");
24
gap> fd:=FundamentalDomainStandardSpaceGroup(SpaceGroup(3,9));
<polymake object>
gap> Polymake(fd,"N_VERTICES");
8

4.1-2 FundamentalDomainBieberbachGroup
‣ FundamentalDomainBieberbachGroup( [v, ]G[, gram] )( operation )

Returns: a PolymakeObject

Given a starting vector v and a Bieberbach group G in standard form, this method calculates the Dirichlet domain with respect to v. If gram is not supplied, the average gramian matrix is used (see GramianOfAverageScalarProductFromFiniteMatrixGroup (2.3-1)). It is not tested if gram is symmetric and positive definite. It is also not tested, if the product defined by gram is invariant under the point group of G.

The behaviour of this function is influenced by the option ineqThreshold. The algorithm calculates approximations to a fundamental domain by iteratively adding inequalities. For an approximating polyhedron, every vertex is tested to find new inequalities. When all vertices have been considered or the number of new inequalities already found exceeds the value of ineqThreshold, a new approximating polyhedron in calculated. The default for ineqThreshold is 200. Roughly speaking, a large threshold means shifting work from polymake to GAP, a small one means more calls of (and work for) polymake.

If the value of InfoHAPcryst (1.3-1) is 2 or more, for each approximation the number of vertices of the approximation, the number of vertices that have to be considered during the calculation, the number of facets, and new inequalities is shown.

Note that the algorithm chooses vertices in random order and also writes inequalities for polymake in random order.

gap> a0:=[[ 1, 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0, 0 ], 
>     [ 0, 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 0 ], 
>     [ 0, 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, -1, -1, 0 ],
>     [ -1/2, 0, 0, 1/6, 0, 0, 1 ] 
>     ];;
gap> a1:=[[ 0, -1, 0, 0, 0, 0, 0 ],[ 0, 0, -1, 0, 0, 0, 0 ],
>         [ 1, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 0 ], 
>         [ 0, 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 1, 0 ],
>         [ 0, 0, 0, 0, 1/3, -1/3, 1 ] 
>        ];;
gap> trans:=List(Group((1,2,3,4,5,6)),g->
>           TranslationOnRightFromVector(Permuted([1,0,0,0,0,0],g)));;
gap> S:=AffineCrystGroupOnRight(Concatenation(trans,[a0,a1]));
<matrix group with 8 generators>
gap> SetInfoLevel(InfoHAPcryst,2);
gap> FundamentalDomainBieberbachGroup(S:ineqThreshold:=10);
#I  v: 104/104 f:15
#I  new: 201
#I  v: 961/961 f:58
#I  new: 20
#I  v: 1143/805 f:69
#I  new: 12
#I  v: 1059/555 f:64
#I  new: 15
#I  v: 328/109 f:33
#I  new: 12
#I  v: 336/58 f:32
#I  new: 0
<polymake object>
gap> FundamentalDomainBieberbachGroup(S:ineqThreshold:=1000);
#I  v: 104/104 f:15
#I  new: 149
#I  v: 635/635 f:41
#I  new: 115
#I  v: 336/183 f:32
#I  new: 0
#I  out of inequalities
<polymake object>

4.1-3 FundamentalDomainFromGeneralPointAndOrbitPartGeometric
‣ FundamentalDomainFromGeneralPointAndOrbitPartGeometric( v, orbit )( method )

Returns: a PolymakeObject

This uses an alternative algorithm based on geometric considerations. It is not used in any of the high-level methods. Let v be a vector and orbit a sufficiently large part of the orbit of v under a crystallographic group with standard- orthogonal point group (satisfying A^t=A^-1). A geometric algorithm is then used to calculate the Dirichlet domain with respect to v. This also works for crystallographic groups which are not Bieberbach. The point v has to have trivial stabilizer.
The intersection of the full orbit with the unit cube around v is sufficiently large.

gap> G:=SpaceGroup(3,9);;
gap> v:=[0,0,0];
[ 0, 0, 0 ]
gap> orbit:=OrbitStabilizerInUnitCubeOnRight(G,v).orbit;
[ [ 0, 0, 0 ], [ 0, 0, 1/2 ] ]
gap> fd:=FundamentalDomainFromGeneralPointAndOrbitPartGeometric(v,orbit);
<polymake object>
gap> Polymake(fd,"N_VERTICES");
8

4.1-4 IsFundamentalDomainStandardSpaceGroup
‣ IsFundamentalDomainStandardSpaceGroup( poly, G )( method )

Returns: true or false

This tests if a PolymakeObject poly is a fundamental domain for the affine crystallographic group G in standard form.
The function tests the following: First, does the orbit of any vertex of poly have a point inside poly (if this is the case, false is returned). Second: Is every facet of poly the image of a different facet under a group element which does not fix poly. If this is satisfied, true is returned.

4.1-5 IsFundamentalDomainBieberbachGroup
‣ IsFundamentalDomainBieberbachGroup( poly, G )( method )

Returns: true, false or fail

This tests if a PolymakeObject poly is a fundamental domain for the affine crystallographic group G in standard form and if this group is torsion free (ie a Bieberbach group)
It returns true if G is torsion free and poly is a fundamental domain for G. If poly is not a fundamental domain, false is returned regardless of the structure of G. And if G is not torsion free, the method returns fail. If G is polycyclic, torsion freeness is tested using a representation as pcp group. Otherwise the stabilisers of the faces of the fundamental domain poly are calculated (G is torsion free if and only if it all these stabilisers are trivial).

4.2 Face Lattice and Resolution

For Bieberbach groups (torsion free crystallographic groups), the following functions calcualte free resolutions. This calculation is done by finding a fundamental domain for the group. For a description of the HapResolution datatype, see the Hap data types documentation or the experimental datatypes documentation A

4.2-1 ResolutionBieberbachGroup
‣ ResolutionBieberbachGroup( G[, v] )( method )

Returns: a HAPresolution

Let G be a Bieberbach group given as an AffineCrystGroupOnRight and v a vector. Then a Dirichlet domain with respect to v is calculated using FundamentalDomainBieberbachGroup (4.1-2). From this domain, a resolution is calculated using FaceLatticeAndBoundaryBieberbachGroup (4.2-2) and ResolutionFromFLandBoundary (4.2-3). If v is not given, the origin is used.

gap> R:=ResolutionBieberbachGroup(SpaceGroup(3,9));
Resolution of length 3 in characteristic
0 for SpaceGroupOnRightBBNWZ( 3, 2, 2, 2, 2 ) .
No contracting homotopy available.

gap> List([0..3],Dimension(R));
[ 1, 3, 3, 1 ]
gap> R:=ResolutionBieberbachGroup(SpaceGroup(3,9),[1/2,0,0]);
Resolution of length 3 in characteristic
0 for SpaceGroupOnRightBBNWZ( 3, 2, 2, 2, 2 ) .
No contracting homotopy available.

gap> List([0..3],Dimension(R));
[ 6, 12, 7, 1 ]

4.2-2 FaceLatticeAndBoundaryBieberbachGroup
‣ FaceLatticeAndBoundaryBieberbachGroup( poly, group )( method )

Returns: Record with entries .hasse and .elts representing a part of the hasse diagram and a lookup table of group elements

Let group be a torsion free AffineCrystGroupOnRight (that is, a Bieberbach group). Given a PolymakeObject poly representing a fundamental domain for group, this method uses polymaking to calculate the face lattice of poly. From the set of faces, a system of representatives for group- orbits is chosen. For each representative, the boundary is then calculated. The list .elts contains elements of group (in fact, it is even a set). The structure of the returned list .hasse is as follows:

  • The i-th entry contains a system of representatives for the i-1 dimensional faces of poly.

  • Each face is represented by a pair of lists [vertices,boundary]. The list of integers vertices represents the vertices of poly which are contained in this face. The enumeration is chosen such that an i in the list represents the i-th entry of the list Polymake(poly,"VERTICES");

  • The list boundary represents the boundary of the respective face. It is a list of pairs of integers [j,g]. The first entry lies between -n and n, where n is the number of faces of dimension i-1. This entry represents a face of dimension i-1 (or its additive inverse as a module generator). The second entry g is the position of the matrix in .elts.

This representation is compatible with the representation of free Z G modules in Hap and this method essentially calculates a free resolution of group. If the value of InfoHAPcryst (1.3-1) is 2 or more, additional information about the number of faces in every codimension, the number of orbits of the group on the free module generated by those faces, and the time it took to calculate the orbit decomposition is output.

gap> SetInfoLevel(InfoHAPcryst,2);
gap> G:=SpaceGroup(3,165);
SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 )
gap> fd:=FundamentalDomainBieberbachGroup(G);
<polymake object>
gap> fl:=FaceLatticeAndBoundaryBieberbachGroup(fd,G);;
#I  1(4/8): 0:00:00.004
#I  2(5/18): 0:00:00.000
#I  3(2/12): 0:00:00.000
#I  Face lattice done ( 0:00:00.004). Calculating boundary
#I  done ( 0:00:00.004) Reformating...
gap> RecNames(fl);
[ "hasse", "elts", "groupring" ]
gap> fl.groupring;
<free left module over Integers, and ring-with-one, with 10 generators>

4.2-3 ResolutionFromFLandBoundary
‣ ResolutionFromFLandBoundary( fl, group )( method )

Returns: Free resolution

If fl is the record output by FaceLatticeAndBoundaryBieberbachGroup (4.2-2) and group is the corresponding group, this function returns a HapResolution. Of course, fl has to be generated from a fundamental domain for group

gap> G:=SpaceGroup(3,165);
SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 )
gap> fd:=FundamentalDomainBieberbachGroup(G);
<polymake object>
gap> fl:=FaceLatticeAndBoundaryBieberbachGroup(fd,G);;
gap> ResolutionFromFLandBoundary(fl,G);
Resolution of length 3 in characteristic
0 for SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) .
No contracting homotopy available.

gap> ResolutionFromFLandBoundary(fl,G);
Resolution of length 3 in characteristic
0 for SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) .
No contracting homotopy available.

gap> List([0..4],Dimension(last));
[ 2, 5, 4, 1, 0 ]
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/chapBib_mj.html0000644000175100017510000000555015160525022016430 0ustar runnerrunner GAP (HAPcryst) - References
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

References

[EGN] Eick, B., Gahler, F. and Nickel, W., cryst, {https://www.gap-system.org/Packages/cryst.html}.

[Ell] Ellis, G., HAP, {http://hamilton.nuigalway.ie/Hap/www/}.

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/chap3_mj.html0000644000175100017510000005121215160525022016072 0ustar runnerrunner GAP (HAPcryst) - Chapter 3: Algorithms of Orbit-Stabilizer Type
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

3 Algorithms of Orbit-Stabilizer Type

We introduce a way to calculate a sufficient part of an orbit and the stabilizer of a point.

3.1 Orbit Stabilizer for Crystallographic Groups

3.1-1 OrbitStabilizerInUnitCubeOnRight
‣ OrbitStabilizerInUnitCubeOnRight( group, x )( method )

Returns: A record containing

  • .stabilizer: the stabilizer of x.

  • .orbit set of vectors from \([0,1)^n\) which represents the orbit.

Let x be a rational vector from \([0,1)^n\) and group a space group in standard form. The function then calculates the part of the orbit which lies inside the cube \([0,1)^n\) and the stabilizer of x. Observe that every element of the full orbit differs from a point in the returned orbit only by a pure translation.

Note that the restriction to points from \([0,1)^n\) makes sense if orbits should be compared and the vector passed to OrbitStabilizerInUnitCubeOnRight should be an element of the returned orbit (part).

gap> S:=SpaceGroup(3,5);;
gap> OrbitStabilizerInUnitCubeOnRight(S,[1/2,0,9/11]);   
rec( orbit := [ [ 0, 1/2, 2/11 ], [ 1/2, 0, 9/11 ] ], 
  stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], 
          [ 0, 0, 0, 1 ] ] ]) )
gap> OrbitStabilizerInUnitCubeOnRight(S,[0,0,0]);     
rec( orbit := [ [ 0, 0, 0 ] ], stabilizer := <matrix group with 2 generators> )

If you are interested in other parts of the orbit, you can use VectorModOne (2.1-2) for the base point and the functions ShiftedOrbitPart (3.1-9), TranslationsToOneCubeAroundCenter (3.1-10) and TranslationsToBox (3.1-11) for the resulting orbit
Suppose we want to calculate the part of the orbit of [4/3,5/3,7/3] in the cube of sidelength 1 around this point:

gap> S:=SpaceGroup(3,5);;
gap> p:=[4/3,5/3,7/3];;
gap> o:=OrbitStabilizerInUnitCubeOnRight(S,VectorModOne(p)).orbit;
[ [ 1/3, 2/3, 1/3 ], [ 1/3, 2/3, 2/3 ] ]
gap> box:=p+[[-1,1],[-1,1],[-1,1]];
[ [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ] ]
gap> o2:=Concatenation(List(o,i->i+TranslationsToBox(i,box)));;
gap> # This is what we looked for. But it is somewhat large:
gap> Size(o2);
54

3.1-2 OrbitStabilizerInUnitCubeOnRightOnSets
‣ OrbitStabilizerInUnitCubeOnRightOnSets( group, set )( method )

Returns: A record containing

  • .stabilizer: the stabilizer of set.

  • .orbit set of sets of vectors from \([0,1)^n\) which represents the orbit.

Calculates orbit and stabilizer of a set of vectors. Just as OrbitStabilizerInUnitCubeOnRight (3.1-1), it needs input from \([0,1)^n\). The returned orbit part .orbit is a set of sets such that every element of .orbit has a non-trivial intersection with the cube \([0,1)^n\). In general, these sets will not lie inside \([0,1)^n\) completely.

gap> S:=SpaceGroup(3,5);;
gap> OrbitStabilizerInUnitCubeOnRightOnSets(S,[[0,0,0],[0,1/2,0]]);
rec( orbit := [ [ [ -1/2, 0, 0 ], [ 0, 0, 0 ] ], 
                [ [ 0, 0, 0 ], [ 0, 1/2, 0 ] ],
                [ [ 1/2, 0, 0 ], [ 1, 0, 0 ] ] ],
  stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], 
                        [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ]) )

3.1-3 OrbitPartInVertexSetsStandardSpaceGroup
‣ OrbitPartInVertexSetsStandardSpaceGroup( group, vertexset, allvertices )( method )

Returns: Set of subsets of allvertices.

If allvertices is a set of vectors and vertexset is a subset thereof, then OrbitPartInVertexSetsStandardSpaceGroup returns that part of the orbit of vertexset which consists entirely of subsets of allvertices. Note that,unlike the other OrbitStabilizer algorithms, this does not require the input to lie in some particular part of the space.

gap> S:=SpaceGroup(3,5);;
gap> OrbitPartInVertexSetsStandardSpaceGroup(S,[[0,1,5],[1,2,0]],
> Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]]));
[ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 2, 6 ], [ 2, 3, 1 ] ] ]
gap> OrbitPartInVertexSetsStandardSpaceGroup(S, [[1,2,0]],
> Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]]));
[ [ [ 0, 1, 5 ] ], [ [ 1, 1, 0 ] ], [ [ 1, 2, 0 ] ], [ [ 1, 2, 6 ] ], [ [ 2, 3, 1 ] ] ]

3.1-4 OrbitPartInFacesStandardSpaceGroup
‣ OrbitPartInFacesStandardSpaceGroup( group, vertexset, faceset )( method )

Returns: Set of subsets of faceset.

This calculates the orbit of a space group on sets restricted to a set of faces.
If faceset is a set of sets of vectors and vertexset is an element of faceset, then OrbitPartInFacesStandardSpaceGroup returns that part of the orbit of vertexset which consists entirely of elements of faceset.
Note that,unlike the other OrbitStabilizer algorithms, this does not require the input to lie in some particular part of the space.

3.1-5 OrbitPartAndRepresentativesInFacesStandardSpaceGroup
‣ OrbitPartAndRepresentativesInFacesStandardSpaceGroup( group, vertexset, faceset )( method )

Returns: A set of face-matrix pairs .

This is a slight variation of OrbitPartInFacesStandardSpaceGroup (3.1-4) that also returns a representative for every orbit element.

gap> S:=SpaceGroup(3,5);;
gap> OrbitPartInVertexSetsStandardSpaceGroup(S,[[0,1,5],[1,2,0]],
> Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]]));
[ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 2, 6 ], [ 2, 3, 1 ] ] ]
gap> OrbitPartInFacesStandardSpaceGroup(S,[[0,1,5],[1,2,0]],
> Set( [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [[1/17,6,1/2],[1,2,7]]]));
[ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ] ]
gap> OrbitPartAndRepresentativesInFacesStandardSpaceGroup(S,[[0,1,5],[1,2,0]],
> Set( [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [[1/17,6,1/2],[1,2,7]]]));
[ [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ],
      [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ] ]

3.1-6 StabilizerOnSetsStandardSpaceGroup
‣ StabilizerOnSetsStandardSpaceGroup( group, set )( method )

Returns: finite group of affine matrices (OnRight)

Given a set set of vectors and a space group group in standard form, this method calculates the stabilizer of that set in the full crystallographic group.

 
gap> G:=SpaceGroup(3,12);;
gap> v:=[ 0, 0,0 ];;
gap> s:=StabilizerOnSetsStandardSpaceGroup(G,[v]);
<matrix group with 2 generators>
gap> s2:=OrbitStabilizerInUnitCubeOnRight(G,v).stabilizer;
<matrix group with 2 generators>
gap> s2=s;
true

3.1-7 RepresentativeActionOnRightOnSets
‣ RepresentativeActionOnRightOnSets( group, set, imageset )( method )

Returns: Affine matrix.

Returns an element of the space group \(S\) which takes the set set to the set imageset. The group must be in standard form and act on the right.

gap> S:=SpaceGroup(3,5);;
gap> RepresentativeActionOnRightOnSets(G, [[0,0,0],[0,1/2,0]],
>        [ [ 0, 1/2, 0 ], [ 0, 1, 0 ] ]);
[ [ 0, -1, 0, 0 ], [ -1, 0, 0, 0 ], [ 0, 0, -1, 0 ], [ 0, 1, 0, 1 ] ]

3.1-8 Getting other orbit parts

HAPcryst does not calculate the full orbit but only the part of it having coefficients between \(-1/2\) and \(1/2\). The other parts of the orbit can be calculated using the following functions.

3.1-9 ShiftedOrbitPart
‣ ShiftedOrbitPart( point, orbitpart )( method )

Returns: Set of vectors

Takes each vector in orbitpart to the cube unit cube centered in point.

gap> ShiftedOrbitPart([0,0,0],[[1/2,1/2,1/3],-[1/2,1/2,1/2],[19,3,1]]);
[ [ 1/2, 1/2, 1/3 ], [ 1/2, 1/2, 1/2 ], [ 0, 0, 0 ] ]
gap> ShiftedOrbitPart([1,1,1],[[1/2,1/2,1/2],-[1/2,1/2,1/2]]);
[ [ 3/2, 3/2, 3/2 ] ]

3.1-10 TranslationsToOneCubeAroundCenter
‣ TranslationsToOneCubeAroundCenter( point, center )( method )

Returns: List of integer vectors

This method returns the list of all integer vectors which translate point into the box center\(+[-1/2,1/2]^n\)

gap> TranslationsToOneCubeAroundCenter([1/2,1/2,1/3],[0,0,0]);
[ [ 0, 0, 0 ], [ 0, -1, 0 ], [ -1, 0, 0 ], [ -1, -1, 0 ] ]
gap> TranslationsToOneCubeAroundCenter([1,0,1],[0,0,0]);
[ [ -1, 0, -1 ] ]

3.1-11 TranslationsToBox
‣ TranslationsToBox( point, box )( method )

Returns: List of integer vectors or the empty list

Given a vector \(v\) and a list of pairs, this function returns the translation vectors (integer vectors) which take \(v\) into the box box. The box box has to be given as a list of pairs.

gap> TranslationsToBox([0,0],[[1/2,2/3],[1/2,2/3]]);
[  ]
gap> TranslationsToBox([0,0],[[-3/2,1/2],[1,4/3]]);
[ [ -1, 1 ], [ 0, 1 ] ]
gap> TranslationsToBox([0,0],[[-3/2,1/2],[2,1]]);
Error, Box must not be empty
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/chapC.html0000644000175100017510000001704215160525022015427 0ustar runnerrunner GAP (HAPcryst) - Appendix C: Contracting Homotopies
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

C Contracting Homotopies

C.1 The PartialContractingHomotopy Data Type

A partial contracting homotopy is a component object that knows the values of a contracting homotopy on some subspace of a resolution. It has two mandatory components:

  • .resolution a HapResolution on which the contraction is defined.

  • .knownPartOfHomotopy a list of Records with components .space and .map.

Let h be a contracting homotopy. The lookup table .knownPartOfHomotopy has one entry for each term of the resolution h.resolution (that is, one more than Length(h.resolution)).

The i th element of .knownPartOfHomotopy contains a record with components .space and .map where .space is a FreeZGWord of the i-1 st term of the resolution. The component .map is a list of length Dimension(h.resolution)(i-1). The entries of this list are pairs [g,im] where g represents a group element and im represents the image of the contraction. So the entry [g,im] in the kth component of the list .map means that the kth free generator of the corresponding module multiplied with the group element represented by g is mapped to im under the partial contracting homotopy. Note that the data type of g or im are not fixed at this level. They must be specified by the sub representations. Also, im need not represent the actual image under a contracting homotopy. It is possible to just store a bit of information that is then used to generate the actual image.

As this is a very general data type, it has very few methods.

C.1-1 ResolutionOfContractingHomotopy
‣ ResolutionOfContractingHomotopy( homotopy )( method )

Returns: A HapResolution

This returns the resolution of the homotopy homotopy (the component homotopy!.resolution).

C.1-2 PartialContractingHomotopyLookup
‣ PartialContractingHomotopyLookup( homotopy, term, generator, groupel )( method )
‣ PartialContractingHomotopyLookupNC( homotopy, term, generator, groupel )( method )

Returns: The entry im of the corresponding lookup table

Looks up the known part of the contracting homotopy homotopy and returns the corresponding image. More precisely, it returns the image of the generatorth generator times the group element represented by groupel in term term under the partial homotopy. The data type of this image depends on the representation of homotopy.

term has to be an integer and generator a positive integer. groupel only has to be an Object.

The NC version does not do any checks on the input. The other version checks if term and generator are sensible. It does not check groupel.

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/HAPcryst.bib0000644000175100017510000000113715160525022015674 0ustar runnerrunner@Misc{polymake, author = "Ewgenij Gawrilow and Michael Joswig", title = {polymake}, howpublished = {{https://polymake.org}} } @Misc{polyhedral, author = {Dutour Sikiric, Mathieu}, title = {Polyhedral}, howpublished = {{http://www.liga.ens.fr/~dutour/Polyhedral/index.html}} } @Misc{hap, author = {Graham Ellis}, title = {HAP}, howpublished = {{http://hamilton.nuigalway.ie/Hap/www/}} } @Misc{cryst, author = "Bettina Eick and Franz Gahler and Werner Nickel", title = {cryst}, howpublished = {{https://www.gap-system.org/Packages/cryst.html}} } hapcryst-0.2.0/doc/chap1.html0000644000175100017510000002254615160525022015412 0ustar runnerrunner GAP (HAPcryst) - Chapter 1: Introduction
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

1 Introduction

1.1 Abstract and Notation

HAPcryst is an extension for "Homological Algebra Programming" (HAP, [Ell]) by Graham Ellis. It uses geometric methods to calculate resolutions for crystallographic groups. In this manual, we will use the terms "space group" and "crystallographic group" synonymous. As usual in GAP, group elements are supposed to act from the right. To emphasize this fact, some functions have names ending in "OnRight" (namely those, which rely on the action from the right). This is also meant to make work with HAPcryst and cryst [EGN] easier.

The functions called "somethingStandardSpaceGroup" are supposed to work for standard crystallographic groups on left and right some time in the future. Currently only the versions acting on right are implemented. As in cryst [EGN], space groups are represented as affine linear groups. For the computations in HAPcryst, crystallographic groups have to be in "standard form". That is, the translation basis has to be the standard basis of the space. This implies that the linear part of a group element need not be orthogonal with respect to the usual scalar product.

1.1-1 The natural action of crystallographic groups

There is some confusion about the way crystallographic groups are written. This concerns the question if we act on left or on right and if vectors are of the form [1,...] or [...,1].

As mentioned, HAPcryst handles affine crystallographic groups on right (and maybe later also on left) acting on vectors of the form [...,1].

BUT: The functions in HAPcryst do not take augmented vectors as input (no leading or ending ones). The handling of vectors is done internally. So in HAPcryst, a crystallographic group is a group of nĂ— n matrices which acts on a vector space of dimension n-1 whose elements are vectors of length n-1 (not n). Example:

gap> G:=SpaceGroup(3,4); #This group acts on 3-Space
SpaceGroupOnRightBBNWZ( 3, 2, 1, 1, 2 )
gap> Display(Representative(G));
[ [  1,  0,  0,  0 ],
  [  0,  1,  0,  0 ],
  [  0,  0,  1,  0 ],
  [  0,  0,  0,  1 ] ]
gap> OrbitStabilizerInUnitCubeOnRight(G,[1/2,0,0]);
rec( orbit := [ [ 1/2, 0, 0 ], [ 1/2, 1/2, 0 ] ],
  stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ],
          [ 0, 0, 0, 1 ] ] ]) )

1.2 Requirements

The following GAP packages are required

  • polymaking which in turn depends on the computational geometry software polymake.

  • HAP

  • Cryst

The following GAP packages are not required but highly recommended:

  • carat

  • CrystCat

  • GAPDoc is needed to display the online manual

1.2-1 Recommendation concerning polymake

Calculating resolutions of Bieberbach groups involves convex hull computations. polymake by default uses cdd to compute convex hulls. Experiments suggest that lrs is the more suitable algorithm for the computations done in HAPcryst than the default cdd. You can change the behaviour of by editing the file "yourhomedirectory/.polymake/prefer.pl". It should contain a section like this (just make sure lrs is before cdd, the position of beneath_beyond does not matter):

#########################################
application polytope;

prefer "*.convex_hull  lrs, beneath_beyond, cdd";

1.3 Global Variables

HAPcryst itself does only have one global variable, namely InfoHAPcryst (1.3-1). The location of files generated for interaction with polymake are determined by the value of POLYMAKE_DATA_DIR (polymaking: POLYMAKE_DATA_DIR) which is a global variable of polymaking.

1.3-1 InfoHAPcryst
‣ InfoHAPcryst( info class )

At a level of 1, only the most important messages are printed. At level 2, additional information is displayed, and level 3 is even more verbose. At level 0, HAPcryst remains silent.

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/geometry.xml0000644000175100017510000001257715160525022016110 0ustar runnerrunner
Face Lattice and Resolution For Bieberbach groups (torsion free crystallographic groups), the following functions calcualte free resolutions. This calculation is done by finding a fundamental domain for the group. For a description of the HapResolution datatype, see the Hap data types documentation or the experimental datatypes documentation a HAPresolution Let G be a Bieberbach group given as an AffineCrystGroupOnRight and v a vector. Then a Dirichlet domain with respect to v is calculated using . From this domain, a resolution is calculated using and . If v is not given, the origin is used. R:=ResolutionBieberbachGroup(SpaceGroup(3,9)); Resolution of length 3 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 2, 2, 2, 2 ) . No contracting homotopy available. gap> List([0..3],Dimension(R)); [ 1, 3, 3, 1 ] gap> R:=ResolutionBieberbachGroup(SpaceGroup(3,9),[1/2,0,0]); Resolution of length 3 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 2, 2, 2, 2 ) . No contracting homotopy available. gap> List([0..3],Dimension(R)); [ 6, 12, 7, 1 ] ]]> Record with entries .hasse and .elts representing a part of the hasse diagram and a lookup table of group elements Let group be a torsion free AffineCrystGroupOnRight (that is, a Bieberbach group). Given a PolymakeObject poly representing a fundamental domain for group, this method uses polymaking to calculate the face lattice of poly. From the set of faces, a system of representatives for group- orbits is chosen. For each representative, the boundary is then calculated. The list .elts contains elements of group (in fact, it is even a set). The structure of the returned list .hasse is as follows: The i-th entry contains a system of representatives for the i-1 dimensional faces of poly. Each face is represented by a pair of lists [vertices,boundary]. The list of integers vertices represents the vertices of poly which are contained in this face. The enumeration is chosen such that an i in the list represents the i-th entry of the list Polymake(poly,"VERTICES"); The list boundary represents the boundary of the respective face. It is a list of pairs of integers [j,g]. The first entry lies between -n and n, where n is the number of faces of dimension i-1. This entry represents a face of dimension i-1 (or its additive inverse as a module generator). The second entry g is the position of the matrix in .elts. This representation is compatible with the representation of free \mathbb Z G modules in Hap and this method essentially calculates a free resolution of group. If the value of is 2 or more, additional information about the number of faces in every codimension, the number of orbits of the group on the free module generated by those faces, and the time it took to calculate the orbit decomposition is output. SetInfoLevel(InfoHAPcryst,2); gap> G:=SpaceGroup(3,165); SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) gap> fd:=FundamentalDomainBieberbachGroup(G); gap> fl:=FaceLatticeAndBoundaryBieberbachGroup(fd,G);; #I 1(4/8): 0:00:00.004 #I 2(5/18): 0:00:00.000 #I 3(2/12): 0:00:00.000 #I Face lattice done ( 0:00:00.004). Calculating boundary #I done ( 0:00:00.004) Reformating... gap> RecNames(fl); [ "hasse", "elts", "groupring" ] gap> fl.groupring; ]]> Free resolution If fl is the record output by and group is the corresponding group, this function returns a HapResolution. Of course, fl has to be generated from a fundamental domain for group G:=SpaceGroup(3,165); SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) gap> fd:=FundamentalDomainBieberbachGroup(G); gap> fl:=FaceLatticeAndBoundaryBieberbachGroup(fd,G);; gap> ResolutionFromFLandBoundary(fl,G); Resolution of length 3 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) . No contracting homotopy available. gap> ResolutionFromFLandBoundary(fl,G); Resolution of length 3 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) . No contracting homotopy available. gap> List([0..4],Dimension(last)); [ 2, 5, 4, 1, 0 ] ]]>
hapcryst-0.2.0/doc/contraction.xml0000644000175100017510000000605515160525022016572 0ustar runnerrunner
The PartialContractingHomotopy Data Type A partial contracting homotopy is a component object that knows the values of a contracting homotopy on some subspace of a resolution. It has two mandatory components: .resolution a HapResolution on which the contraction is defined. .knownPartOfHomotopy a list of Records with components .space and .map. Let h be a contracting homotopy. The lookup table .knownPartOfHomotopy has one entry for each term of the resolution h.resolution (that is, one more than Length(h.resolution)).

The i th element of .knownPartOfHomotopy contains a record with components .space and .map where .space is a FreeZGWord of the i-1 st term of the resolution. The component .map is a list of length Dimension(h.resolution)(i-1). The entries of this list are pairs [g,im] where g represents a group element and im represents the image of the contraction. So the entry [g,im] in the kth component of the list .map means that the kth free generator of the corresponding module multiplied with the group element represented by g is mapped to im under the partial contracting homotopy. Note that the data type of g or im are not fixed at this level. They must be specified by the sub representations. Also, im need not represent the actual image under a contracting homotopy. It is possible to just store a bit of information that is then used to generate the actual image.

As this is a very general data type, it has very few methods. A HapResolution This returns the resolution of the homotopy homotopy (the component homotopy!.resolution). The entry im of the corresponding lookup table Looks up the known part of the contracting homotopy homotopy and returns the corresponding image. More precisely, it returns the image of the generatorth generator times the group element represented by groupel in term term under the partial homotopy. The data type of this image depends on the representation of homotopy.

term has to be an integer and generator a positive integer. groupel only has to be an Object.

The NC version does not do any checks on the input. The other version checks if term and generator are sensible. It does not check groupel.

hapcryst-0.2.0/doc/chapInd.html0000644000175100017510000002604415160525022015761 0ustar runnerrunner GAP (HAPcryst) - Index
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

Index

action of crystallographic groups 1.1-1
BasisChangeAffineMatOnRight 2.2-2
BisectorInequalityFromPointPair 2.3-3
BoundaryOfFreeZGLetter B.1-9
BoundaryOfFreeZGLetter_LargeGroupRep B.4-11
BoundaryOfFreeZGLetterNC B.3-6
BoundaryOfFreeZGLetterNC_LargeGroupRep B.4-11
BoundaryOfFreeZGWord B.1-10
BoundaryOfFreeZGWord_LargeGroupRep B.4-12
BoundaryOfFreeZGWordNC B.3-7
BoundaryOfGenerator_LargeGroupRep B.4-10
BoundaryOfGeneratorNC_LargeGroupRep B.4-10
ConvertLetterToStandardRep B.2-3
ConvertLetterToStandardRepNC B.2-3
ConvertStandardLetter B.2-1
ConvertStandardLetterNC B.2-1
ConvertStandardWord B.2-2
ConvertStandardWordNC B.2-2
ConvertWordToStandardRep B.2-4
ConvertWordToStandardRepNC B.2-4
DimensionSquareMat 2.1-4
FaceLatticeAndBoundaryBieberbachGroup 4.2-2
FundamentalDomainBieberbachGroup 4.1-2
FundamentalDomainFromGeneralPointAndOrbitPartGeometric 4.1-3
FundamentalDomainStandardSpaceGroup 4.1-1
GeneratorsOfModuleOfResolution_LargeGroupRep B.4-9
GramianOfAverageScalarProductFromFiniteMatrixGroup 2.3-1
GroupElementFromPosition B.1-5
GroupRingOfResolution B.4-1
ineqThreshold 4.1-2
InfoHAPcryst 1.3-1
installation 1.2
IsFreeZGLetter B.3-1
IsFreeZGLetter_LargeGroupRep B.4-5
IsFreeZGLetterNoTermCheck_LargeGroupRep B.4-3
IsFreeZGWord B.3-2
IsFreeZGWord_LargeGroupRep B.4-6
IsFreeZGWordNoTermCheck_LargeGroupRep B.4-4
IsFundamentalDomainBieberbachGroup 4.1-5
IsFundamentalDomainStandardSpaceGroup 4.1-4
IsSquareMat 2.1-3
IsValidGroupInt B.1-4
LinearPartOfAffineMatOnRight 2.2-1
MultiplyFreeZGLetterWithGroupElt B.1-7
MultiplyFreeZGLetterWithGroupElt_LargeGroupRep B.4-7
MultiplyFreeZGLetterWithGroupEltNC B.3-4
MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep B.4-7
MultiplyFreeZGWordWithGroupElt B.1-8
MultiplyFreeZGWordWithGroupElt_LargeGroupRep B.4-8
MultiplyFreeZGWordWithGroupEltNC B.3-5
MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep B.4-8
MultiplyGroupElts B.1-6
MultiplyGroupElts_LargeGroupRep B.4-2
MultiplyGroupEltsNC B.3-3
MultiplyGroupEltsNC_LargeGroupRep B.4-2
OrbitPartAndRepresentativesInFacesStandardSpaceGroup 3.1-5
OrbitPartInFacesStandardSpaceGroup 3.1-4
OrbitPartInVertexSetsStandardSpaceGroup 3.1-3
OrbitStabilizerInUnitCubeOnRight 3.1-1
OrbitStabilizerInUnitCubeOnRightOnSets 3.1-2
PartialContractingHomotopyLookup C.1-2
PartialContractingHomotopyLookupNC C.1-2
PointGroupRepresentatives 2.4-1
polymake 1.2-1
PositionInGroupOfResolution B.1-3
PositionInGroupOfResolutionNC B.1-3
RelativePositionPointAndPolygon 2.3-5
RepresentativeActionOnRightOnSets 3.1-7
ResolutionBieberbachGroup 4.2-1
ResolutionFromFLandBoundary 4.2-3
ResolutionOfContractingHomotopy C.1-1
ShiftedOrbitPart 3.1-9
SignRat 2.1-1
StabilizerOnSetsStandardSpaceGroup 3.1-6
StrongestValidRepresentationForLetter B.1-1
StrongestValidRepresentationForWord B.1-2
TranslationOnRightFromVector 2.2-3
TranslationsToBox 3.1-11
TranslationsToOneCubeAroundCenter 3.1-10
VectorModOne 2.1-2
WhichSideOfHyperplane 2.3-4
WhichSideOfHyperplaneNC 2.3-4

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/chapA.html0000644000175100017510000002135515160525022015427 0ustar runnerrunner GAP (HAPcryst) - Appendix A: Resolutions in Hap
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

A Resolutions in Hap

This document is only concerned with the representation of resolutions in Hap. Note that it is not a part of Hap. The framework provided here is just an extension of Hap data types used in HAPcryst and HAPprime.

From now on, let G be a group and dots -> M_n-> M_n-1->dots-> M_1-> M_0-> Z be a resolution with free ZG modules M_i.

The elements of the modules M_i can be represented in different ways. This is what makes different representations for resolutions desirable. First, we will look at the standard representation (HapResolutionRep) as it is defined in Hap. After that, we will present another representation for infinite groups. Note that all non-standard representations must be sub-representations of the standard representation to ensure compatibility with Hap.

A.1 The Standard Representation HapResolutionRep

For every M_i we fix a basis and number its elements. Furthermore, it is assumed that we have a (partial) enumeration of the group of a resolution. In practice this is done by generating a lookup table on the fly.

In standard representation, the elements of the modules M_k are represented by lists -"words"- of pairs of integers. A letter [i,g] of such a word consists of the number of a basis element i or -i for its additive inverse and a number g representing a group element.

A HapResolution in HapResolutionRep representation is a component object with the components

  • group, a group of arbitrary type.

  • elts, a (partial) list of (possibly duplicate) elements in G. This list provides the "enumeration" of the group. Note that there are functions in Hap which assume that elts[1] is the identity element of G.

  • appendToElts(g) a function that appends the group element g to .elts. This is not documented in Hap 1.8.6 but seems to be required for infinite groups. This requirement might vanish in some later version of Hap [G. Ellis, private communication].

  • dimension(k), a function which returns the ZG-rank of the Module M_k

  • boundary(k,j), a function which returns the image in M_k-1 of the jth free generator of M_k. Note that negative j are valid as input as well. In this case the additive inverse of the boundary of the jth generator is returned

  • homotopy(k,[i,g]) a function which returns the image in M_k+1, under a contracting homotopy M_k -> M_k+1, of the element [[i,g]] in M_k. The value of this might be fail. However, currently (version 1.8.4) some Hap functions assume that homotopy is a function without testing.

  • properties, a list of pairs ["name","value"] "name" is a string and value is anything (boolean, number, string...). Every HapResolution (regardless of representation) has to have ["type","resolution"], ["length",length] where length is the length of the resolution and ["characteristic",char]. Currently (Hap 1.8.6), length must not be infinity. The values of these properties can be tested using the Hap function EvaluateProperty(resolution,propertyname).

Note that making HapResolutions immutable will make the .elts component immutable. As this lookup table might change during calculations, we do not recommend using immutable resolutions (in any representation).

A.2 The HapLargeGroupResolutionRep Representation

In this sub-representation of the standard representation, the module elements in this resolution are lists of groupring elements. So the lookup table .elts is not used as long as no conversion to standard representation takes place. In addition to the components of a HapResolution, a resolution in large group representation has the following components:

  • boundary2(resolution,term,gen), a function that returns the boundary of the genth generator of the termth module.

  • groupring the group ring of the resolution resolution.

  • dimension2(resolution,term) a function that returns the dimension of the termth module of the resolution resolution.

The effort of having two versions of boundary and dimension is necessary to keep the structure compatible with the usual Hap resolution.

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/rainbow.js0000644000175100017510000000533615160525022015525 0ustar runnerrunner function randchar(str) { var i = Math.floor(Math.random() * str.length); while (i == str.length) i = Math.floor(Math.random() * str.length); return str[i]; } hexdigits = "0123456789abcdef"; function randlight() { return randchar("cdef")+randchar(hexdigits)+ randchar("cdef")+randchar(hexdigits)+ randchar("cdef")+randchar(hexdigits) } function randdark() { return randchar("012345789")+randchar(hexdigits)+ randchar("012345789")+randchar(hexdigits)+ randchar("102345789")+randchar(hexdigits) } document.write('\n'); hapcryst-0.2.0/doc/chap1.txt0000644000175100017510000001232015160525022015252 0ustar runnerrunner 1 Introduction 1.1 Abstract and Notation HAPcryst is an extension for "Homological Algebra Programming" (HAP, [Ell]) by Graham Ellis. It uses geometric methods to calculate resolutions for crystallographic groups. In this manual, we will use the terms "space group" and "crystallographic group" synonymous. As usual in GAP, group elements are supposed to act from the right. To emphasize this fact, some functions have names ending in "OnRight" (namely those, which rely on the action from the right). This is also meant to make work with HAPcryst and cryst [EGN] easier. The functions called "somethingStandardSpaceGroup" are supposed to work for standard crystallographic groups on left and right some time in the future. Currently only the versions acting on right are implemented. As in cryst [EGN], space groups are represented as affine linear groups. For the computations in HAPcryst, crystallographic groups have to be in "standard form". That is, the translation basis has to be the standard basis of the space. This implies that the linear part of a group element need not be orthogonal with respect to the usual scalar product. 1.1-1 The natural action of crystallographic groups There is some confusion about the way crystallographic groups are written. This concerns the question if we act on left or on right and if vectors are of the form [1,...] or [...,1]. As mentioned, HAPcryst handles affine crystallographic groups on right (and maybe later also on left) acting on vectors of the form [...,1]. BUT: The functions in HAPcryst do not take augmented vectors as input (no leading or ending ones). The handling of vectors is done internally. So in HAPcryst, a crystallographic group is a group of nĂ— n matrices which acts on a vector space of dimension n-1 whose elements are vectors of length n-1 (not n). Example:  Example  gap> G:=SpaceGroup(3,4); #This group acts on 3-Space SpaceGroupOnRightBBNWZ( 3, 2, 1, 1, 2 ) gap> Display(Representative(G)); [ [ 1, 0, 0, 0 ],  [ 0, 1, 0, 0 ],  [ 0, 0, 1, 0 ],  [ 0, 0, 0, 1 ] ] gap> OrbitStabilizerInUnitCubeOnRight(G,[1/2,0,0]); rec( orbit := [ [ 1/2, 0, 0 ], [ 1/2, 1/2, 0 ] ],  stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ],  [ 0, 0, 0, 1 ] ] ]) )  1.2 Requirements The following GAP packages are required  polymaking which in turn depends on the computational geometry software polymake.  HAP  Cryst The following GAP packages are not required but highly recommended:  carat  CrystCat  GAPDoc is needed to display the online manual 1.2-1 Recommendation concerning polymake Calculating resolutions of Bieberbach groups involves convex hull computations. polymake by default uses cdd to compute convex hulls. Experiments suggest that lrs is the more suitable algorithm for the computations done in HAPcryst than the default cdd. You can change the behaviour of by editing the file "yourhomedirectory/.polymake/prefer.pl". It should contain a section like this (just make sure lrs is before cdd, the position of beneath_beyond does not matter):  ######################################### application polytope;  prefer "*.convex_hull lrs, beneath_beyond, cdd";  1.3 Global Variables HAPcryst itself does only have one global variable, namely InfoHAPcryst (1.3-1). The location of files generated for interaction with polymake are determined by the value of POLYMAKE_DATA_DIR (polymaking: POLYMAKE_DATA_DIR) which is a global variable of polymaking. 1.3-1 InfoHAPcryst InfoHAPcryst  info class At a level of 1, only the most important messages are printed. At level 2, additional information is displayed, and level 3 is even more verbose. At level 0, HAPcryst remains silent. hapcryst-0.2.0/doc/chapA_mj.html0000644000175100017510000002201115160525022016103 0ustar runnerrunner GAP (HAPcryst) - Appendix A: Resolutions in Hap
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

A Resolutions in Hap

This document is only concerned with the representation of resolutions in Hap. Note that it is not a part of Hap. The framework provided here is just an extension of Hap data types used in HAPcryst and HAPprime.

From now on, let \(G\) be a group and \(\dots \to M_n\to M_{n-1}\to\dots\to M_1\to M_0\to Z\) be a resolution with free \(ZG\) modules \(M_i\).

The elements of the modules \(M_i\) can be represented in different ways. This is what makes different representations for resolutions desirable. First, we will look at the standard representation (HapResolutionRep) as it is defined in Hap. After that, we will present another representation for infinite groups. Note that all non-standard representations must be sub-representations of the standard representation to ensure compatibility with Hap.

A.1 The Standard Representation HapResolutionRep

For every \(M_i\) we fix a basis and number its elements. Furthermore, it is assumed that we have a (partial) enumeration of the group of a resolution. In practice this is done by generating a lookup table on the fly.

In standard representation, the elements of the modules \(M_k\) are represented by lists -"words"- of pairs of integers. A letter [i,g] of such a word consists of the number of a basis element i or -i for its additive inverse and a number \(g\) representing a group element.

A HapResolution in HapResolutionRep representation is a component object with the components

  • group, a group of arbitrary type.

  • elts, a (partial) list of (possibly duplicate) elements in G. This list provides the "enumeration" of the group. Note that there are functions in Hap which assume that elts[1] is the identity element of G.

  • appendToElts(g) a function that appends the group element g to .elts. This is not documented in Hap 1.8.6 but seems to be required for infinite groups. This requirement might vanish in some later version of Hap [G. Ellis, private communication].

  • dimension(k), a function which returns the ZG-rank of the Module \(M_k\)

  • boundary(k,j), a function which returns the image in \(M_{k-1}\) of the \(j\)th free generator of \(M_k\). Note that negative \(j\) are valid as input as well. In this case the additive inverse of the boundary of the \(j\)th generator is returned

  • homotopy(k,[i,g]) a function which returns the image in \(M_{k+1}\), under a contracting homotopy \(M_k \to M_{k+1}\), of the element [[i,g]] in \(M_k\). The value of this might be fail. However, currently (version 1.8.4) some Hap functions assume that homotopy is a function without testing.

  • properties, a list of pairs ["name","value"] "name" is a string and value is anything (boolean, number, string...). Every HapResolution (regardless of representation) has to have ["type","resolution"], ["length",length] where length is the length of the resolution and ["characteristic",char]. Currently (Hap 1.8.6), length must not be infinity. The values of these properties can be tested using the Hap function EvaluateProperty(resolution,propertyname).

Note that making HapResolutions immutable will make the .elts component immutable. As this lookup table might change during calculations, we do not recommend using immutable resolutions (in any representation).

A.2 The HapLargeGroupResolutionRep Representation

In this sub-representation of the standard representation, the module elements in this resolution are lists of groupring elements. So the lookup table .elts is not used as long as no conversion to standard representation takes place. In addition to the components of a HapResolution, a resolution in large group representation has the following components:

  • boundary2(resolution,term,gen), a function that returns the boundary of the genth generator of the termth module.

  • groupring the group ring of the resolution resolution.

  • dimension2(resolution,term) a function that returns the dimension of the termth module of the resolution resolution.

The effort of having two versions of boundary and dimension is necessary to keep the structure compatible with the usual Hap resolution.

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/title.xml0000644000175100017510000000157215160525022015367 0ustar runnerrunner HAPcryst A HAP extension for crystallographic groups Version 0.2.0 Marc Roeder
roeder.marc@gmail.com
24 March 2026 ©right; 2007 Marc Röder.

This package is distributed under the terms of the GNU General Public License version 2 or later (at your convenience). See the file LICENSE or https://www.gnu.org/copyleft/gpl.html This work was supported by Marie Curie Grant No. MTKD-CT-2006-042685 hapcryst-0.2.0/doc/manual.lab0000644000175100017510000002105715160525022015461 0ustar runnerrunner\GAPDocLabFile{hapcryst} \makelabel{hapcryst:Title page}{}{X7D2C85EC87DD46E5} \makelabel{hapcryst:Copyright}{}{X81488B807F2A1CF1} \makelabel{hapcryst:Acknowledgements}{}{X82A988D47DFAFCFA} \makelabel{hapcryst:Table of Contents}{}{X8537FEB07AF2BEC8} \makelabel{hapcryst:Introduction}{1}{X7DFB63A97E67C0A1} \makelabel{hapcryst:Abstract and Notation}{1.1}{X813275957BA5B5E0} \makelabel{hapcryst:The natural action of crystallographic groups}{1.1.1}{X7F4A00F481A1FB39} \makelabel{hapcryst:Requirements}{1.2}{X85A08CF187A6D986} \makelabel{hapcryst:Recommendation concerning polymake}{1.2.1}{X7990986A8114E0DB} \makelabel{hapcryst:Global Variables}{1.3}{X7D9044767BEB1523} \makelabel{hapcryst:Bits and Pieces}{2}{X86FBE5B77C2F9442} \makelabel{hapcryst:Matrices and Vectors}{2.1}{X8019925B8294F5B4} \makelabel{hapcryst:Affine Matrices OnRight}{2.2}{X86BD4FE4871379AD} \makelabel{hapcryst:Geometry}{2.3}{X84A0B0637F269E37} \makelabel{hapcryst:Inequalities}{2.3.2}{X866942167802E036} \makelabel{hapcryst:Space Groups}{2.4}{X7B14774981F80108} \makelabel{hapcryst:Algorithms of Orbit-Stabilizer Type}{3}{X7F6789767FB36E74} \makelabel{hapcryst:Orbit Stabilizer for Crystallographic Groups}{3.1}{X85CAB2EB85A6E17A} \makelabel{hapcryst:Getting other orbit parts}{3.1.8}{X8002407080DB3EA2} \makelabel{hapcryst:Resolutions of Crystallographic Groups}{4}{X852C41A77C759D82} \makelabel{hapcryst:Fundamental Domains}{4.1}{X7F48638F817A14B0} \makelabel{hapcryst:Face Lattice and Resolution}{4.2}{X78D68F6087238F97} \makelabel{hapcryst:Resolutions in Hap}{A}{X7C6DD73E7BB931AB} \makelabel{hapcryst:The Standard Representation HapResolutionRep}{A.1}{X804F611B7E23BDB1} \makelabel{hapcryst:The HapLargeGroupResolutionRep Representation}{A.2}{X8024014D8488FE30} \makelabel{hapcryst:Accessing and Manipulating Resolutions}{B}{X86374CEA7CDC6946} \makelabel{hapcryst:Representation-Independent Access Methods}{B.1}{X7A7225067E7895A9} \makelabel{hapcryst:Converting Between Representations}{B.2}{X7B94A2ED857C62D5} \makelabel{hapcryst:Special Methods for HapResolutionRep}{B.3}{X84FB45EB83B5822C} \makelabel{hapcryst:The HapLargeGroupResolutionRep Representation}{B.4}{X8024014D8488FE30} \makelabel{hapcryst:Contracting Homotopies}{C}{X792B9CC97C670AEA} \makelabel{hapcryst:The PartialContractingHomotopy Data Type}{C.1}{X7E957D2381DBE362} \makelabel{hapcryst:Bibliography}{Bib}{X7A6F98FD85F02BFE} \makelabel{hapcryst:References}{Bib}{X7A6F98FD85F02BFE} \makelabel{hapcryst:Index}{Ind}{X83A0356F839C696F} \makelabel{hapcryst:action of crystallographic groups}{1.1.1}{X7F4A00F481A1FB39} \makelabel{hapcryst:installation}{1.2}{X85A08CF187A6D986} \makelabel{hapcryst:polymake}{1.2.1}{X7990986A8114E0DB} \makelabel{hapcryst:InfoHAPcryst}{1.3.1}{X78B0A21E7FD0F3BB} \makelabel{hapcryst:SignRat}{2.1.1}{X7D58A1848182EC26} \makelabel{hapcryst:VectorModOne}{2.1.2}{X7C0552BA873515B9} \makelabel{hapcryst:IsSquareMat}{2.1.3}{X7BB083A57C474F45} \makelabel{hapcryst:DimensionSquareMat}{2.1.4}{X78C932A48515EF10} \makelabel{hapcryst:LinearPartOfAffineMatOnRight}{2.2.1}{X838946957FC75C17} \makelabel{hapcryst:BasisChangeAffineMatOnRight}{2.2.2}{X80DD4F2286D49F8D} \makelabel{hapcryst:TranslationOnRightFromVector}{2.2.3}{X81F3C49580958FB6} \makelabel{hapcryst:GramianOfAverageScalarProductFromFiniteMatrixGroup}{2.3.1}{X7A94DAE679AD73E3} \makelabel{hapcryst:BisectorInequalityFromPointPair}{2.3.3}{X80C365AA87BDDAFA} \makelabel{hapcryst:WhichSideOfHyperplane}{2.3.4}{X8790464D86D189F4} \makelabel{hapcryst:WhichSideOfHyperplaneNC}{2.3.4}{X8790464D86D189F4} \makelabel{hapcryst:RelativePositionPointAndPolygon}{2.3.5}{X83392C417B311B6B} \makelabel{hapcryst:PointGroupRepresentatives}{2.4.1}{X7E2F20607F278B70} \makelabel{hapcryst:OrbitStabilizerInUnitCubeOnRight}{3.1.1}{X7BED233684B2F811} \makelabel{hapcryst:OrbitStabilizerInUnitCubeOnRightOnSets}{3.1.2}{X82BD20307A67C119} \makelabel{hapcryst:OrbitPartInVertexSetsStandardSpaceGroup}{3.1.3}{X82CCCD597C86A08A} \makelabel{hapcryst:OrbitPartInFacesStandardSpaceGroup}{3.1.4}{X8022CD75819DE536} \makelabel{hapcryst:OrbitPartAndRepresentativesInFacesStandardSpaceGroup}{3.1.5}{X86A80FA17A4D6664} \makelabel{hapcryst:StabilizerOnSetsStandardSpaceGroup}{3.1.6}{X81DE08687F0DBCC6} \makelabel{hapcryst:RepresentativeActionOnRightOnSets}{3.1.7}{X83C6448679A54F9D} \makelabel{hapcryst:ShiftedOrbitPart}{3.1.9}{X8751429287034F4A} \makelabel{hapcryst:TranslationsToOneCubeAroundCenter}{3.1.10}{X82656DE584E8DC5D} \makelabel{hapcryst:TranslationsToBox}{3.1.11}{X858C787E83A902AB} \makelabel{hapcryst:FundamentalDomainStandardSpaceGroup}{4.1.1}{X79F4F7938116201E} \makelabel{hapcryst:FundamentalDomainBieberbachGroup}{4.1.2}{X7A07AB55831F212F} \makelabel{hapcryst:ineqThreshold}{4.1.2}{X7A07AB55831F212F} \makelabel{hapcryst:FundamentalDomainFromGeneralPointAndOrbitPartGeometric}{4.1.3}{X86A09AC4842827C9} \makelabel{hapcryst:IsFundamentalDomainStandardSpaceGroup}{4.1.4}{X824BC99584F5F865} \makelabel{hapcryst:IsFundamentalDomainBieberbachGroup}{4.1.5}{X7D79DD6E87BCC1DC} \makelabel{hapcryst:ResolutionBieberbachGroup}{4.2.1}{X7CA87AA478007468} \makelabel{hapcryst:FaceLatticeAndBoundaryBieberbachGroup}{4.2.2}{X7E854FC47F9E479E} \makelabel{hapcryst:ResolutionFromFLandBoundary}{4.2.3}{X79A0B28A7FAE31B9} \makelabel{hapcryst:StrongestValidRepresentationForLetter}{B.1.1}{X7CBC6D4C783383BE} \makelabel{hapcryst:StrongestValidRepresentationForWord}{B.1.2}{X7C10841285614D04} \makelabel{hapcryst:PositionInGroupOfResolution}{B.1.3}{X780AD2DB7F5D4935} \makelabel{hapcryst:PositionInGroupOfResolutionNC}{B.1.3}{X780AD2DB7F5D4935} \makelabel{hapcryst:IsValidGroupInt}{B.1.4}{X7A58EC7B8130D6E2} \makelabel{hapcryst:GroupElementFromPosition}{B.1.5}{X822604B67B2A9133} \makelabel{hapcryst:MultiplyGroupElts}{B.1.6}{X7D3673E8840FA0B6} \makelabel{hapcryst:MultiplyFreeZGLetterWithGroupElt}{B.1.7}{X8540F3B37BAC695F} \makelabel{hapcryst:MultiplyFreeZGWordWithGroupElt}{B.1.8}{X826835B185CA4DAF} \makelabel{hapcryst:BoundaryOfFreeZGLetter}{B.1.9}{X7D8B54D7828D7C5C} \makelabel{hapcryst:BoundaryOfFreeZGWord}{B.1.10}{X81A6037F82C3C31E} \makelabel{hapcryst:ConvertStandardLetter}{B.2.1}{X7EB515317948BE8E} \makelabel{hapcryst:ConvertStandardLetterNC}{B.2.1}{X7EB515317948BE8E} \makelabel{hapcryst:ConvertStandardWord}{B.2.2}{X7A1CB5DF7A459D76} \makelabel{hapcryst:ConvertStandardWordNC}{B.2.2}{X7A1CB5DF7A459D76} \makelabel{hapcryst:ConvertLetterToStandardRep}{B.2.3}{X83153E2682184860} \makelabel{hapcryst:ConvertLetterToStandardRepNC}{B.2.3}{X83153E2682184860} \makelabel{hapcryst:ConvertWordToStandardRep}{B.2.4}{X848203218271A166} \makelabel{hapcryst:ConvertWordToStandardRepNC}{B.2.4}{X848203218271A166} \makelabel{hapcryst:IsFreeZGLetter}{B.3.1}{X7B803CC184BD2612} \makelabel{hapcryst:IsFreeZGWord}{B.3.2}{X7A36FB7B84E9A892} \makelabel{hapcryst:MultiplyGroupEltsNC}{B.3.3}{X836D3F9886EED6AC} \makelabel{hapcryst:MultiplyFreeZGLetterWithGroupEltNC}{B.3.4}{X85893CC5823508A8} \makelabel{hapcryst:MultiplyFreeZGWordWithGroupEltNC}{B.3.5}{X8073DE7E7AD8B7CB} \makelabel{hapcryst:BoundaryOfFreeZGLetterNC}{B.3.6}{X7BD3994E7C414149} \makelabel{hapcryst:BoundaryOfFreeZGWordNC}{B.3.7}{X84B1DA21805A0880} \makelabel{hapcryst:GroupRingOfResolution}{B.4.1}{X861BE6C787FA8032} \makelabel{hapcryst:MultiplyGroupEltsLargeGroupRep}{B.4.2}{X8338F7A37F240E33} \makelabel{hapcryst:MultiplyGroupEltsNCLargeGroupRep}{B.4.2}{X8338F7A37F240E33} \makelabel{hapcryst:IsFreeZGLetterNoTermCheckLargeGroupRep}{B.4.3}{X86F91A948022DEBB} \makelabel{hapcryst:IsFreeZGWordNoTermCheckLargeGroupRep}{B.4.4}{X793BA61478AEBE16} \makelabel{hapcryst:IsFreeZGLetterLargeGroupRep}{B.4.5}{X85A7BFC284E9D9CB} \makelabel{hapcryst:IsFreeZGWordLargeGroupRep}{B.4.6}{X7BF4A7EC83BE61C8} \makelabel{hapcryst:MultiplyFreeZGLetterWithGroupEltLargeGroupRep}{B.4.7}{X7A4B682079630694} \makelabel{hapcryst:MultiplyFreeZGLetterWithGroupEltNCLargeGroupRep}{B.4.7}{X7A4B682079630694} \makelabel{hapcryst:MultiplyFreeZGWordWithGroupEltLargeGroupRep}{B.4.8}{X7F2365D2851E3E3C} \makelabel{hapcryst:MultiplyFreeZGWordWithGroupEltNCLargeGroupRep}{B.4.8}{X7F2365D2851E3E3C} \makelabel{hapcryst:GeneratorsOfModuleOfResolutionLargeGroupRep}{B.4.9}{X8355F6E8842B3D8C} \makelabel{hapcryst:BoundaryOfGeneratorLargeGroupRep}{B.4.10}{X840DF79086D5473E} \makelabel{hapcryst:BoundaryOfGeneratorNCLargeGroupRep}{B.4.10}{X840DF79086D5473E} \makelabel{hapcryst:BoundaryOfFreeZGLetterNCLargeGroupRep}{B.4.11}{X83D90EC28357DCCE} \makelabel{hapcryst:BoundaryOfFreeZGLetterLargeGroupRep}{B.4.11}{X83D90EC28357DCCE} \makelabel{hapcryst:BoundaryOfFreeZGWordLargeGroupRep}{B.4.12}{X78C681D37F8DC2A1} \makelabel{hapcryst:ResolutionOfContractingHomotopy}{C.1.1}{X7D899ACD7EB512FA} \makelabel{hapcryst:PartialContractingHomotopyLookup}{C.1.2}{X79C69C9B877C6D60} \makelabel{hapcryst:PartialContractingHomotopyLookupNC}{C.1.2}{X79C69C9B877C6D60} hapcryst-0.2.0/doc/chapB_mj.html0000644000175100017510000011500515160525022016112 0ustar runnerrunner GAP (HAPcryst) - Appendix B: Accessing and Manipulating Resolutions

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

B Accessing and Manipulating Resolutions

B Accessing and Manipulating Resolutions

B.1 Representation-Independent Access Methods

All methods listed below take a HapResolution in any representation. If the other arguments are compatible with the representation of the resolution, the returned value will be in the form defined by this representation. If the other arguments are in a different representation, GAPs method selection is used via TryNextMethod() to find an applicable method (a suitable representation).

The idea behind this is that the results of computations have the same form as the input. And as all representations are sub-representations of the HapResolutionRep representation, input which is compatible with the HapResolutionRep representation is always valid.

Every new representation must support the functions of this section.

B.1-1 StrongestValidRepresentationForLetter
‣ StrongestValidRepresentationForLetter( resolution, term, letter )( method )

Returns: filter

Finds the sub-representation of HapResolutionRep for which letter is a valid letter of the termth module of resolution. Note that resolution automatically is in some sub-representation of HapResolutionRep.This is mainly meant for debugging.

B.1-2 StrongestValidRepresentationForWord
‣ StrongestValidRepresentationForWord( resolution, term, word )( method )

Returns: filter

Finds the sub-representation of HapResolutionRep for which word is a valid word of the termth module of resolution. Note that resolution automatically is in some sub-representation of HapResolutionRep. This is mainly meant for debugging.

B.1-3 PositionInGroupOfResolution
‣ PositionInGroupOfResolution( resolution, g )( method )
‣ PositionInGroupOfResolutionNC( resolution, g )( method )

Returns: positive integer

This returns the position of the group element g in the enumeration of the group of resolution. The NC version does not check if g really is an element of the group of resolution.

B.1-4 IsValidGroupInt
‣ IsValidGroupInt( resolution, n )( method )

Returns: boolean

Returns true if the nth element of the group of resolution is known.

B.1-5 GroupElementFromPosition
‣ GroupElementFromPosition( resolution, n )( method )

Returns: group element or fail

Returns nth element of the group of resolution. If the nth element is not known, fail is returned.

B.1-6 MultiplyGroupElts
‣ MultiplyGroupElts( resolution, x, y )( method )

Returns: positive integer or group element, depending on the type of x and y

If x and y are given in standard representation (i.e. as integers), this returns the position of the product of the group elements represented by the positive integers x and x.

If x and y are given in any other representation, the returned group element will also be represented in this way.

B.1-7 MultiplyFreeZGLetterWithGroupElt
‣ MultiplyFreeZGLetterWithGroupElt( resolution, letter, g )( method )

Returns: A letter

Multiplies the letter letter with the group element g and returns the result. If resolution is in standard representation, g has to be an integer and letter has to be a pair of integer. If resolution is in any other representation, letter and g can be in a form compatible with that representation or in the standard form (in the latter case, the returned value will also have standard form).

B.1-8 MultiplyFreeZGWordWithGroupElt
‣ MultiplyFreeZGWordWithGroupElt( resolution, word, g )( method )

Returns: A word

Multiplies the word word with the group element g and returns the result. If resolution is in standard representation, g has to be an integer and word has to be a list of pairs of integers. If resolution is in any other representation, word and g can be in a form compatible with that representation or in the standard form (in the latter case, the returned value will also have standard form).

B.1-9 BoundaryOfFreeZGLetter
‣ BoundaryOfFreeZGLetter( resolution, term, letter )( method )

Returns: free ZG word (in the same representation as letter)

Calculates the boundary of the letter (word of length 1) letter of the termth module of resolution.

The returned value is a word of the term-1st module and comes in the same representation as letter.

B.1-10 BoundaryOfFreeZGWord
‣ BoundaryOfFreeZGWord( resolution, term, word )( method )

Returns: free ZG word (in the same representation as letter)

Calculates the boundary of the word word of the termth module of resolution.

The returned value is a word of the term-1st module and comes in the same representation as word.

B.2 Converting Between Representations

Four methods are provided to convert letters and words from standard representation to any other representation and back again.

B.2-1 ConvertStandardLetter
‣ ConvertStandardLetter( resolution, term, letter )( method )
‣ ConvertStandardLetterNC( resolution, term, letter )( method )

Returns: letter in the representation of resolution

Converts the letter letter in standard representation to the representation of resolution. The NC version does not check whether letter really is a letter in standard representation.

B.2-2 ConvertStandardWord
‣ ConvertStandardWord( resolution, term, word )( method )
‣ ConvertStandardWordNC( resolution, term, word )( method )

Returns: word in the representation of resolution

Converts the word word in standard representation to the representation of resolution. The NC version does not check whether word is a valid word in standard representation.

B.2-3 ConvertLetterToStandardRep
‣ ConvertLetterToStandardRep( resolution, term, letter )( method )
‣ ConvertLetterToStandardRepNC( resolution, term, letter )( method )

Returns: letter in standard representation

Converts the letter letter in the representation of resolution to the standard representation. The NC version does not check whether letter is a valid letter of resolution.

B.2-4 ConvertWordToStandardRep
‣ ConvertWordToStandardRep( resolution, term, word )( method )
‣ ConvertWordToStandardRepNC( resolution, term, word )( method )

Returns: word in standard representation

Converts the word word in the representation of resolution to the standard representation. The NC version does not check whether word is a valid word of resolution.

B.3 Special Methods for HapResolutionRep

Some methods explicitely require the input to be in the standard representation (HapResolutionRep). Two of these test if a word/letter is really in standard representation, the other ones are non-check versions of the universal methods.

B.3-1 IsFreeZGLetter
‣ IsFreeZGLetter( resolution, term, letter )( method )

Returns: boolean

Checks if letter is an valid letter (word of length 1) in standard representation of the termth module of resolution.

B.3-2 IsFreeZGWord
‣ IsFreeZGWord( resolution, term, word )( method )

Returns: boolean

Check if word is a valid word in large standard representation of the termth module in resolution.

B.3-3 MultiplyGroupEltsNC
‣ MultiplyGroupEltsNC( resolution, x, y )( method )

Returns: positive integer

Given positive integers x and y, this returns the position of the product of the group elements represented by the positive integers x and x. This assumes that all input is in standard representation and does not check the input.

B.3-4 MultiplyFreeZGLetterWithGroupEltNC
‣ MultiplyFreeZGLetterWithGroupEltNC( resolution, letter, g )( method )

Returns: A letter in standard representation

Multiplies the letter letter with the group element represented by the positive integer g and returns the result. The input is assumed to be in HapResolutionRep and is not checked.

B.3-5 MultiplyFreeZGWordWithGroupEltNC
‣ MultiplyFreeZGWordWithGroupEltNC( resolution, word, g )( method )

Returns: A letter in standard representation

Multiplies the word word with the group element represented by the positive integer g and returns the result. The input is assumed to be in HapResolutionRep and is not checked.

B.3-6 BoundaryOfFreeZGLetterNC
‣ BoundaryOfFreeZGLetterNC( resolution, term, letter )( method )

Returns: free ZG word in standard representation

Calculates the boundary of the letter (word of length 1) letter of the termth module of resolution. The input is assumed to be in standard representation and not checked.

B.3-7 BoundaryOfFreeZGWordNC
‣ BoundaryOfFreeZGWordNC( resolution, term, word )( method )

Returns: free ZG word in standard representation

Calculates the boundary of the word word of the termth module of resolution. The input is assumed to be in standard representation and not checked.

B.4 The HapLargeGroupResolutionRep Representation

The large group representation has one additional component called groupring. Elements of the modules in a resolution are represented by lists of group ring elements. The length of the list corresponds to the dimension of the free module.

All methods for the generic representation do also work for the large group representation. Some of them are wrappers for special methods which do only work for this representation. The following list only contains the methods which are not already present in the generic representation.

Note that the input or the output of these functions does not comply with the standard representation.

B.4-1 GroupRingOfResolution
‣ GroupRingOfResolution( resolution )( method )

Returns: group ring

This returns the group ring of resolution. Note that by the way that group rings are handled in GAP, this is not equal to GroupRing(R,GroupOfResolution(resolution)) where R is the ring of the resolution.

B.4-2 MultiplyGroupElts_LargeGroupRep
‣ MultiplyGroupElts_LargeGroupRep( resolution, x, y )( method )
‣ MultiplyGroupEltsNC_LargeGroupRep( resolution, x, y )( method )

Returns: group element

Returns the product of x and y. The NC version does not check whether x and y are actually elements of the group of resolution.

B.4-3 IsFreeZGLetterNoTermCheck_LargeGroupRep
‣ IsFreeZGLetterNoTermCheck_LargeGroupRep( resolution, letter )( method )

Returns: boolean

Returns true if letter has the form of a letter (a module element with exactly one non-zero entry which has exactly one non-zero coefficient) a module of resolution in the HapLargeGroupResolution representation. Note that it is not tested if letter actually is a letter in any term of resolution

B.4-4 IsFreeZGWordNoTermCheck_LargeGroupRep
‣ IsFreeZGWordNoTermCheck_LargeGroupRep( resolution, word )( method )

Returns: boolean

Returns true if word has the form of a word of a module of resolution in the HapLargeGroupResolution representation. Note that it is not tested if word actually is a word in any term of resolution.

B.4-5 IsFreeZGLetter_LargeGroupRep
‣ IsFreeZGLetter_LargeGroupRep( resolution, term, letter )( method )

Returns: boolean

Returns true if and only if letter is a letter (a word of length 1) of the termth module of resolution in the hapLargeGroupResolution representation. I.e. it tests if letter is a module element with exactly one non-zero entry which has exactly one non-zero coefficient.

B.4-6 IsFreeZGWord_LargeGroupRep
‣ IsFreeZGWord_LargeGroupRep( resolution, term, word )( method )

Returns: boolean

Tests if word is an element of the termth module of resoultion.

B.4-7 MultiplyFreeZGLetterWithGroupElt_LargeGroupRep
‣ MultiplyFreeZGLetterWithGroupElt_LargeGroupRep( resolution, letter, g )( method )
‣ MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep( resolution, letter, g )( method )

Returns: free ZG letter in large group representation

Multiplies the letter letter with the group element g and returns the result. The NC version does not check whether g is an element of the group of resolution and letter can be a letter.

B.4-8 MultiplyFreeZGWordWithGroupElt_LargeGroupRep
‣ MultiplyFreeZGWordWithGroupElt_LargeGroupRep( resolution, word, g )( method )
‣ MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep( resolution, word, g )( method )

Returns: free ZG word in large group representation

Multiplies the word word with the group element g and returns the result. The NC version does not check whether g is an element of the group of resolution and word can be a word.

B.4-9 GeneratorsOfModuleOfResolution_LargeGroupRep
‣ GeneratorsOfModuleOfResolution_LargeGroupRep( resolution, term )( method )

Returns: list of letters/words in large group representation

Returns a set of generators for the termth module of resolution. The returned value is a list of vectors of group ring elements.

B.4-10 BoundaryOfGenerator_LargeGroupRep
‣ BoundaryOfGenerator_LargeGroupRep( resolution, term, n )( method )
‣ BoundaryOfGeneratorNC_LargeGroupRep( resolution, term, n )( method )

Returns: free ZG word in the large group representation

Returns the boundary of the nth generator of the termth module of resolution as a word in the n-1st module (in large group representation). The NC version does not check whether there is a termth module and if it has at least n generators.

B.4-11 BoundaryOfFreeZGLetterNC_LargeGroupRep
‣ BoundaryOfFreeZGLetterNC_LargeGroupRep( resolution, term, letter )( method )
‣ BoundaryOfFreeZGLetter_LargeGroupRep( resolution, term, letter )( method )

Returns: free ZG word in large group representation

Calculates the boundary of the letter letter of the termth module of resolution in large group representation. The NC version does not check whether letter actually is a letter in the termth module.

B.4-12 BoundaryOfFreeZGWord_LargeGroupRep
‣ BoundaryOfFreeZGWord_LargeGroupRep( resolution, term, word )( method )

Returns: free ZG word in large group representation

Calculates the boundary of the element word of the termth module of resolution in large group representation. The NC version does not check whether word actually is a word in the termth module.

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/chaincomplex.xml0000644000175100017510000000110315160525022016706 0ustar runnerrunner
Chain Complex Given a polyhedron, the face lattice defines a chain complex. This can be done using the following function. A Given a polyhedron poly as generated by polymaking (see ), this method generates the face complex.
hapcryst-0.2.0/doc/manual.six0000644000175100017510000004344315160525022015531 0ustar runnerrunner#SIXFORMAT GapDocGAP HELPBOOKINFOSIXTMP := rec( encoding := "UTF-8", bookname := "HAPcryst", entries := [ [ "Title page", "0.0", [ 0, 0, 0 ], 1, 1, "title page", "X7D2C85EC87DD46E5" ], [ "Copyright", "0.0-1", [ 0, 0, 1 ], 23, 2, "copyright", "X81488B807F2A1CF1" ], [ "Acknowledgements", "0.0-2", [ 0, 0, 2 ], 32, 2, "acknowledgements", "X82A988D47DFAFCFA" ], [ "Table of Contents", "0.0-3", [ 0, 0, 3 ], 37, 3, "table of contents", "X8537FEB07AF2BEC8" ], [ "\033[1X\033[33X\033[0;-2YIntroduction\033[133X\033[101X", "1", [ 1, 0, 0 ], 1, 4, "introduction", "X7DFB63A97E67C0A1" ], [ "\033[1X\033[33X\033[0;-2YAbstract and Notation\033[133X\033[101X", "1.1", [ 1, 1, 0 ], 4, 4, "abstract and notation", "X813275957BA5B5E0" ] , [ "\033[1X\033[33X\033[0;-2YThe natural action of crystallographic groups\\ 033[133X\033[101X", "1.1-1", [ 1, 1, 1 ], 25, 4, "the natural action of crystallographic groups", "X7F4A00F481A1FB39" ], [ "\033[1X\033[33X\033[0;-2YRequirements\033[133X\033[101X", "1.2", [ 1, 2, 0 ], 55, 5, "requirements", "X85A08CF187A6D986" ], [ "\033[1X\033[33X\033[0;-2YRecommendation concerning polymake\033[133X\033[1\ 01X", "1.2-1", [ 1, 2, 1 ], 75, 5, "recommendation concerning polymake", "X7990986A8114E0DB" ], [ "\033[1X\033[33X\033[0;-2YGlobal Variables\033[133X\033[101X", "1.3", [ 1, 3, 0 ], 93, 5, "global variables", "X7D9044767BEB1523" ], [ "\033[1X\033[33X\033[0;-2YBits and Pieces\033[133X\033[101X", "2", [ 2, 0, 0 ], 1, 6, "bits and pieces", "X86FBE5B77C2F9442" ], [ "\033[1X\033[33X\033[0;-2YMatrices and Vectors\033[133X\033[101X", "2.1", [ 2, 1, 0 ], 7, 6, "matrices and vectors", "X8019925B8294F5B4" ], [ "\033[1X\033[33X\033[0;-2YAffine Matrices OnRight\033[133X\033[101X", "2.2", [ 2, 2, 0 ], 64, 7, "affine matrices onright", "X86BD4FE4871379AD" ], [ "\033[1X\033[33X\033[0;-2YGeometry\033[133X\033[101X", "2.3", [ 2, 3, 0 ], 113, 8, "geometry", "X84A0B0637F269E37" ], [ "\033[1X\033[33X\033[0;-2YInequalities\033[133X\033[101X", "2.3-2", [ 2, 3, 2 ], 126, 8, "inequalities", "X866942167802E036" ], [ "\033[1X\033[33X\033[0;-2YSpace Groups\033[133X\033[101X", "2.4", [ 2, 4, 0 ], 182, 9, "space groups", "X7B14774981F80108" ], [ "\033[1X\033[33X\033[0;-2YAlgorithms of Orbit-Stabilizer Type\033[133X\033[\ 101X", "3", [ 3, 0, 0 ], 1, 10, "algorithms of orbit-stabilizer type", "X7F6789767FB36E74" ], [ "\033[1X\033[33X\033[0;-2YOrbit Stabilizer for Crystallographic Groups\033[\ 133X\033[101X", "3.1", [ 3, 1, 0 ], 7, 10, "orbit stabilizer for crystallographic groups", "X85CAB2EB85A6E17A" ], [ "\033[1X\033[33X\033[0;-2YGetting other orbit parts\033[133X\033[101X", "3.1-8", [ 3, 1, 8 ], 177, 13, "getting other orbit parts", "X8002407080DB3EA2" ], [ "\033[1X\033[33X\033[0;-2YResolutions of Crystallographic Groups\033[133X\\ 033[101X", "4", [ 4, 0, 0 ], 1, 15, "resolutions of crystallographic groups", "X852C41A77C759D82" ], [ "\033[1X\033[33X\033[0;-2YFundamental Domains\033[133X\033[101X", "4.1", [ 4, 1, 0 ], 4, 15, "fundamental domains", "X7F48638F817A14B0" ], [ "\033[1X\033[33X\033[0;-2YFace Lattice and Resolution\033[133X\033[101X", "4.2", [ 4, 2, 0 ], 165, 18, "face lattice and resolution", "X78D68F6087238F97" ], [ "\033[1X\033[33X\033[0;-2YResolutions in Hap\033[133X\033[101X", "a", [ "A", 0, 0 ], 1, 21, "resolutions in hap", "X7C6DD73E7BB931AB" ], [ "\033[1X\033[33X\033[0;-2YThe Standard Representation \033[9XHapResolutionR\ ep\033[109X\033[101X\027\033[1X\027\033[133X\033[101X", "a.1", [ "A", 1, 0 ], 19, 21, "the standard representation hapresolutionrep", "X804F611B7E23BDB1" ], [ "\033[1X\033[33X\033[0;-2YThe \033[9XHapLargeGroupResolutionRep\033[109X\\ 033[101X\027\033[1X\027 Representation\033[133X\033[101X", "a.2", [ "A", 2, 0 ], 70, 22, "the haplargegroupresolutionrep representation", "X8024014D8488FE30" ], [ "\033[1X\033[33X\033[0;-2YAccessing and Manipulating Resolutions\033[133X\\ 033[101X", "b", [ "B", 0, 0 ], 1, 23, "accessing and manipulating resolutions" , "X86374CEA7CDC6946" ], [ "\033[1X\033[33X\033[0;-2YRepresentation-Independent Access Methods\033[133\ X\033[101X", "b.1", [ "B", 1, 0 ], 4, 23, "representation-independent access methods", "X7A7225067E7895A9" ], [ "\033[1X\033[33X\033[0;-2YConverting Between Representations\033[133X\033[1\ 01X", "b.2", [ "B", 2, 0 ], 124, 25, "converting between representations", "X7B94A2ED857C62D5" ], [ "\033[1X\033[33X\033[0;-2YSpecial Methods for \033[9XHapResolutionRep\033[1\ 09X\033[101X\027\033[1X\027\033[133X\033[101X", "b.3", [ "B", 3, 0 ], 170, 26, "special methods for hapresolutionrep", "X84FB45EB83B5822C" ], [ "\033[1X\033[33X\033[0;-2YThe \033[9XHapLargeGroupResolutionRep\033[109X\\ 033[101X\027\033[1X\027 Representation\033[133X\033[101X", "b.4", [ "B", 4, 0 ], 239, 27, "the haplargegroupresolutionrep representation", "X8024014D8488FE30" ], [ "\033[1X\033[33X\033[0;-2YContracting Homotopies\033[133X\033[101X", "c", [ "C", 0, 0 ], 1, 30, "contracting homotopies", "X792B9CC97C670AEA" ], [ "\033[1X\033[33X\033[0;-2YThe \033[9XPartialContractingHomotopy\033[109X\ \033[101X\027\033[1X\027 Data Type\033[133X\033[101X", "c.1", [ "C", 1, 0 ], 4, 30, "the partialcontractinghomotopy data type", "X7E957D2381DBE362" ] , [ "Bibliography", "bib", [ "Bib", 0, 0 ], 1, 32, "bibliography", "X7A6F98FD85F02BFE" ], [ "References", "bib", [ "Bib", 0, 0 ], 1, 32, "references", "X7A6F98FD85F02BFE" ], [ "Index", "ind", [ "Ind", 0, 0 ], 1, 33, "index", "X83A0356F839C696F" ], [ "action of crystallographic groups", "1.1-1", [ 1, 1, 1 ], 25, 4, "action of crystallographic groups", "X7F4A00F481A1FB39" ], [ "installation", "1.2", [ 1, 2, 0 ], 55, 5, "installation", "X85A08CF187A6D986" ], [ "polymake", "1.2-1", [ 1, 2, 1 ], 75, 5, "polymake", "X7990986A8114E0DB" ] , [ "\033[2XInfoHAPcryst\033[102X", "1.3-1", [ 1, 3, 1 ], 101, 5, "infohapcryst", "X78B0A21E7FD0F3BB" ], [ "\033[2XSignRat\033[102X", "2.1-1", [ 2, 1, 1 ], 10, 6, "signrat", "X7D58A1848182EC26" ], [ "\033[2XVectorModOne\033[102X", "2.1-2", [ 2, 1, 2 ], 16, 6, "vectormodone", "X7C0552BA873515B9" ], [ "\033[2XIsSquareMat\033[102X", "2.1-3", [ 2, 1, 3 ], 33, 6, "issquaremat", "X7BB083A57C474F45" ], [ "\033[2XDimensionSquareMat\033[102X", "2.1-4", [ 2, 1, 4 ], 38, 6, "dimensionsquaremat", "X78C932A48515EF10" ], [ "\033[2XLinearPartOfAffineMatOnRight\033[102X", "2.2-1", [ 2, 2, 1 ], 67, 7, "linearpartofaffinematonright", "X838946957FC75C17" ], [ "\033[2XBasisChangeAffineMatOnRight\033[102X", "2.2-2", [ 2, 2, 2 ], 73, 7, "basischangeaffinematonright", "X80DD4F2286D49F8D" ], [ "\033[2XTranslationOnRightFromVector\033[102X", "2.2-3", [ 2, 2, 3 ], 92, 7, "translationonrightfromvector", "X81F3C49580958FB6" ], [ "\033[2XGramianOfAverageScalarProductFromFiniteMatrixGroup\033[102X", "2.3-1", [ 2, 3, 1 ], 116, 8, "gramianofaveragescalarproductfromfinitematrixgroup", "X7A94DAE679AD73E3" ], [ "\033[2XBisectorInequalityFromPointPair\033[102X", "2.3-3", [ 2, 3, 3 ], 133, 8, "bisectorinequalityfrompointpair", "X80C365AA87BDDAFA" ], [ "\033[2XWhichSideOfHyperplane\033[102X", "2.3-4", [ 2, 3, 4 ], 145, 8, "whichsideofhyperplane", "X8790464D86D189F4" ], [ "\033[2XWhichSideOfHyperplaneNC\033[102X", "2.3-4", [ 2, 3, 4 ], 145, 8, "whichsideofhyperplanenc", "X8790464D86D189F4" ], [ "\033[2XRelativePositionPointAndPolygon\033[102X", "2.3-5", [ 2, 3, 5 ], 172, 9, "relativepositionpointandpolygon", "X83392C417B311B6B" ], [ "\033[2XPointGroupRepresentatives\033[102X", "2.4-1", [ 2, 4, 1 ], 185, 9, "pointgrouprepresentatives", "X7E2F20607F278B70" ], [ "\033[2XOrbitStabilizerInUnitCubeOnRight\033[102X", "3.1-1", [ 3, 1, 1 ], 10, 10, "orbitstabilizerinunitcubeonright", "X7BED233684B2F811" ], [ "\033[2XOrbitStabilizerInUnitCubeOnRightOnSets\033[102X", "3.1-2", [ 3, 1, 2 ], 60, 11, "orbitstabilizerinunitcubeonrightonsets", "X82BD20307A67C119" ], [ "\033[2XOrbitPartInVertexSetsStandardSpaceGroup\033[102X", "3.1-3", [ 3, 1, 3 ], 86, 11, "orbitpartinvertexsetsstandardspacegroup", "X82CCCD597C86A08A" ], [ "\033[2XOrbitPartInFacesStandardSpaceGroup\033[102X", "3.1-4", [ 3, 1, 4 ], 107, 12, "orbitpartinfacesstandardspacegroup", "X8022CD75819DE536" ], [ "\033[2XOrbitPartAndRepresentativesInFacesStandardSpaceGroup\033[102X", "3.1-5", [ 3, 1, 5 ], 120, 12, "orbitpartandrepresentativesinfacesstandardspacegroup", "X86A80FA17A4D6664" ], [ "\033[2XStabilizerOnSetsStandardSpaceGroup\033[102X", "3.1-6", [ 3, 1, 6 ], 142, 12, "stabilizeronsetsstandardspacegroup", "X81DE08687F0DBCC6" ], [ "\033[2XRepresentativeActionOnRightOnSets\033[102X", "3.1-7", [ 3, 1, 7 ], 162, 13, "representativeactiononrightonsets", "X83C6448679A54F9D" ], [ "\033[2XShiftedOrbitPart\033[102X", "3.1-9", [ 3, 1, 9 ], 184, 13, "shiftedorbitpart", "X8751429287034F4A" ], [ "\033[2XTranslationsToOneCubeAroundCenter\033[102X", "3.1-10", [ 3, 1, 10 ], 198, 13, "translationstoonecubearoundcenter", "X82656DE584E8DC5D" ], [ "\033[2XTranslationsToBox\033[102X", "3.1-11", [ 3, 1, 11 ], 213, 13, "translationstobox", "X858C787E83A902AB" ], [ "\033[2XFundamentalDomainStandardSpaceGroup\033[102X", "4.1-1", [ 4, 1, 1 ], 17, 15, "fundamentaldomainstandardspacegroup", "X79F4F7938116201E" ], [ "\033[2XFundamentalDomainBieberbachGroup\033[102X", "4.1-2", [ 4, 1, 2 ], 39, 15, "fundamentaldomainbieberbachgroup", "X7A07AB55831F212F" ], [ "ineqThreshold", "4.1-2", [ 4, 1, 2 ], 39, 15, "ineqthreshold", "X7A07AB55831F212F" ], [ "\033[2XFundamentalDomainFromGeneralPointAndOrbitPartGeometric\033[102X", "4.1-3", [ 4, 1, 3 ], 110, 17, "fundamentaldomainfromgeneralpointandorbitpartgeometric", "X86A09AC4842827C9" ], [ "\033[2XIsFundamentalDomainStandardSpaceGroup\033[102X", "4.1-4", [ 4, 1, 4 ], 137, 17, "isfundamentaldomainstandardspacegroup", "X824BC99584F5F865" ], [ "\033[2XIsFundamentalDomainBieberbachGroup\033[102X", "4.1-5", [ 4, 1, 5 ], 149, 17, "isfundamentaldomainbieberbachgroup", "X7D79DD6E87BCC1DC" ], [ "\033[2XResolutionBieberbachGroup\033[102X", "4.2-1", [ 4, 2, 1 ], 174, 18, "resolutionbieberbachgroup", "X7CA87AA478007468" ], [ "\033[2XFaceLatticeAndBoundaryBieberbachGroup\033[102X", "4.2-2", [ 4, 2, 2 ], 202, 18, "facelatticeandboundarybieberbachgroup", "X7E854FC47F9E479E" ], [ "\033[2XResolutionFromFLandBoundary\033[102X", "4.2-3", [ 4, 2, 3 ], 257, 19, "resolutionfromflandboundary", "X79A0B28A7FAE31B9" ], [ "\033[2XStrongestValidRepresentationForLetter\033[102X", "b.1-1", [ "B", 1, 1 ], 21, 23, "strongestvalidrepresentationforletter", "X7CBC6D4C783383BE" ], [ "\033[2XStrongestValidRepresentationForWord\033[102X", "b.1-2", [ "B", 1, 2 ], 31, 23, "strongestvalidrepresentationforword", "X7C10841285614D04" ], [ "\033[2XPositionInGroupOfResolution\033[102X", "b.1-3", [ "B", 1, 3 ], 41, 23, "positioningroupofresolution", "X780AD2DB7F5D4935" ], [ "\033[2XPositionInGroupOfResolutionNC\033[102X", "b.1-3", [ "B", 1, 3 ], 41, 23, "positioningroupofresolutionnc", "X780AD2DB7F5D4935" ], [ "\033[2XIsValidGroupInt\033[102X", "b.1-4", [ "B", 1, 4 ], 51, 24, "isvalidgroupint", "X7A58EC7B8130D6E2" ], [ "\033[2XGroupElementFromPosition\033[102X", "b.1-5", [ "B", 1, 5 ], 58, 24, "groupelementfromposition", "X822604B67B2A9133" ], [ "\033[2XMultiplyGroupElts\033[102X", "b.1-6", [ "B", 1, 6 ], 66, 24, "multiplygroupelts", "X7D3673E8840FA0B6" ], [ "\033[2XMultiplyFreeZGLetterWithGroupElt\033[102X", "b.1-7", [ "B", 1, 7 ], 79, 24, "multiplyfreezgletterwithgroupelt", "X8540F3B37BAC695F" ], [ "\033[2XMultiplyFreeZGWordWithGroupElt\033[102X", "b.1-8", [ "B", 1, 8 ], 91, 24, "multiplyfreezgwordwithgroupelt", "X826835B185CA4DAF" ], [ "\033[2XBoundaryOfFreeZGLetter\033[102X", "b.1-9", [ "B", 1, 9 ], 103, 24, "boundaryoffreezgletter", "X7D8B54D7828D7C5C" ], [ "\033[2XBoundaryOfFreeZGWord\033[102X", "b.1-10", [ "B", 1, 10 ], 114, 25, "boundaryoffreezgword", "X81A6037F82C3C31E" ], [ "\033[2XConvertStandardLetter\033[102X", "b.2-1", [ "B", 2, 1 ], 130, 25, "convertstandardletter", "X7EB515317948BE8E" ], [ "\033[2XConvertStandardLetterNC\033[102X", "b.2-1", [ "B", 2, 1 ], 130, 25, "convertstandardletternc", "X7EB515317948BE8E" ], [ "\033[2XConvertStandardWord\033[102X", "b.2-2", [ "B", 2, 2 ], 140, 25, "convertstandardword", "X7A1CB5DF7A459D76" ], [ "\033[2XConvertStandardWordNC\033[102X", "b.2-2", [ "B", 2, 2 ], 140, 25, "convertstandardwordnc", "X7A1CB5DF7A459D76" ], [ "\033[2XConvertLetterToStandardRep\033[102X", "b.2-3", [ "B", 2, 3 ], 150, 25, "convertlettertostandardrep", "X83153E2682184860" ], [ "\033[2XConvertLetterToStandardRepNC\033[102X", "b.2-3", [ "B", 2, 3 ], 150, 25, "convertlettertostandardrepnc", "X83153E2682184860" ], [ "\033[2XConvertWordToStandardRep\033[102X", "b.2-4", [ "B", 2, 4 ], 160, 25, "convertwordtostandardrep", "X848203218271A166" ], [ "\033[2XConvertWordToStandardRepNC\033[102X", "b.2-4", [ "B", 2, 4 ], 160, 25, "convertwordtostandardrepnc", "X848203218271A166" ], [ "\033[2XIsFreeZGLetter\033[102X", "b.3-1", [ "B", 3, 1 ], 178, 26, "isfreezgletter", "X7B803CC184BD2612" ], [ "\033[2XIsFreeZGWord\033[102X", "b.3-2", [ "B", 3, 2 ], 186, 26, "isfreezgword", "X7A36FB7B84E9A892" ], [ "\033[2XMultiplyGroupEltsNC\033[102X", "b.3-3", [ "B", 3, 3 ], 194, 26, "multiplygroupeltsnc", "X836D3F9886EED6AC" ], [ "\033[2XMultiplyFreeZGLetterWithGroupEltNC\033[102X", "b.3-4", [ "B", 3, 4 ], 204, 26, "multiplyfreezgletterwithgroupeltnc", "X85893CC5823508A8" ], [ "\033[2XMultiplyFreeZGWordWithGroupEltNC\033[102X", "b.3-5", [ "B", 3, 5 ], 213, 26, "multiplyfreezgwordwithgroupeltnc", "X8073DE7E7AD8B7CB" ], [ "\033[2XBoundaryOfFreeZGLetterNC\033[102X", "b.3-6", [ "B", 3, 6 ], 222, 26, "boundaryoffreezgletternc", "X7BD3994E7C414149" ], [ "\033[2XBoundaryOfFreeZGWordNC\033[102X", "b.3-7", [ "B", 3, 7 ], 231, 27, "boundaryoffreezgwordnc", "X84B1DA21805A0880" ], [ "\033[2XGroupRingOfResolution\033[102X", "b.4-1", [ "B", 4, 1 ], 255, 27, "groupringofresolution", "X861BE6C787FA8032" ], [ "\033[2XMultiplyGroupElts_LargeGroupRep\033[102X", "b.4-2", [ "B", 4, 2 ], 265, 27, "multiplygroupelts_largegrouprep", "X8338F7A37F240E33" ], [ "\033[2XMultiplyGroupEltsNC_LargeGroupRep\033[102X", "b.4-2", [ "B", 4, 2 ], 265, 27, "multiplygroupeltsnc_largegrouprep", "X8338F7A37F240E33" ], [ "\033[2XIsFreeZGLetterNoTermCheck_LargeGroupRep\033[102X", "b.4-3", [ "B", 4, 3 ], 274, 27, "isfreezgletternotermcheck_largegrouprep", "X86F91A948022DEBB" ], [ "\033[2XIsFreeZGWordNoTermCheck_LargeGroupRep\033[102X", "b.4-4", [ "B", 4, 4 ], 285, 27, "isfreezgwordnotermcheck_largegrouprep", "X793BA61478AEBE16" ], [ "\033[2XIsFreeZGLetter_LargeGroupRep\033[102X", "b.4-5", [ "B", 4, 5 ], 294, 28, "isfreezgletter_largegrouprep", "X85A7BFC284E9D9CB" ], [ "\033[2XIsFreeZGWord_LargeGroupRep\033[102X", "b.4-6", [ "B", 4, 6 ], 304, 28, "isfreezgword_largegrouprep", "X7BF4A7EC83BE61C8" ], [ "\033[2XMultiplyFreeZGLetterWithGroupElt_LargeGroupRep\033[102X", "b.4-7", [ "B", 4, 7 ], 311, 28, "multiplyfreezgletterwithgroupelt_largegrouprep", "X7A4B682079630694" ], [ "\033[2XMultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep\033[102X", "b.4-7", [ "B", 4, 7 ], 311, 28, "multiplyfreezgletterwithgroupeltnc_largegrouprep", "X7A4B682079630694" ], [ "\033[2XMultiplyFreeZGWordWithGroupElt_LargeGroupRep\033[102X", "b.4-8", [ "B", 4, 8 ], 321, 28, "multiplyfreezgwordwithgroupelt_largegrouprep", "X7F2365D2851E3E3C" ], [ "\033[2XMultiplyFreeZGWordWithGroupEltNC_LargeGroupRep\033[102X", "b.4-8", [ "B", 4, 8 ], 321, 28, "multiplyfreezgwordwithgroupeltnc_largegrouprep", "X7F2365D2851E3E3C" ], [ "\033[2XGeneratorsOfModuleOfResolution_LargeGroupRep\033[102X", "b.4-9", [ "B", 4, 9 ], 331, 28, "generatorsofmoduleofresolution_largegrouprep", "X8355F6E8842B3D8C" ], [ "\033[2XBoundaryOfGenerator_LargeGroupRep\033[102X", "b.4-10", [ "B", 4, 10 ], 339, 28, "boundaryofgenerator_largegrouprep", "X840DF79086D5473E" ], [ "\033[2XBoundaryOfGeneratorNC_LargeGroupRep\033[102X", "b.4-10", [ "B", 4, 10 ], 339, 28, "boundaryofgeneratornc_largegrouprep", "X840DF79086D5473E" ], [ "\033[2XBoundaryOfFreeZGLetterNC_LargeGroupRep\033[102X", "b.4-11", [ "B", 4, 11 ], 350, 29, "boundaryoffreezgletternc_largegrouprep", "X83D90EC28357DCCE" ], [ "\033[2XBoundaryOfFreeZGLetter_LargeGroupRep\033[102X", "b.4-11", [ "B", 4, 11 ], 350, 29, "boundaryoffreezgletter_largegrouprep", "X83D90EC28357DCCE" ], [ "\033[2XBoundaryOfFreeZGWord_LargeGroupRep\033[102X", "b.4-12", [ "B", 4, 12 ], 360, 29, "boundaryoffreezgword_largegrouprep", "X78C681D37F8DC2A1" ], [ "\033[2XResolutionOfContractingHomotopy\033[102X", "c.1-1", [ "C", 1, 1 ], 36, 30, "resolutionofcontractinghomotopy", "X7D899ACD7EB512FA" ], [ "\033[2XPartialContractingHomotopyLookup\033[102X", "c.1-2", [ "C", 1, 2 ], 44, 30, "partialcontractinghomotopylookup", "X79C69C9B877C6D60" ], [ "\033[2XPartialContractingHomotopyLookupNC\033[102X", "c.1-2", [ "C", 1, 2 ], 44, 30, "partialcontractinghomotopylookupnc", "X79C69C9B877C6D60" ] ] ); hapcryst-0.2.0/doc/resolutionAccess.xml0000644000175100017510000003637515160525022017604 0ustar runnerrunner Resolutions in Hap This document is only concerned with the representation of resolutions in Hap. Note that it is not a part of Hap. The framework provided here is just an extension of Hap data types used in HAPcryst and HAPprime.

From now on, let G be a group and \dots \to M_n\to M_{n-1}\to\dots\to M_1\to M_0\to Z be a resolution with free ZG modules M_i.

The elements of the modules M_i can be represented in different ways. This is what makes different representations for resolutions desirable. First, we will look at the standard representation (HapResolutionRep) as it is defined in Hap. After that, we will present another representation for infinite groups. Note that all non-standard representations must be sub-representations of the standard representation to ensure compatibility with Hap.

The Standard Representation HapResolutionRep For every M_i we fix a basis and number its elements. Furthermore, it is assumed that we have a (partial) enumeration of the group of a resolution. In practice this is done by generating a lookup table on the fly.

In standard representation, the elements of the modules M_k are represented by lists -"words"- of pairs of integers. A letter [i,g] of such a word consists of the number of a basis element i or -i for its additive inverse and a number g representing a group element.

A HapResolution in HapResolutionRep representation is a component object with the components group, a group of arbitrary type. elts, a (partial) list of (possibly duplicate) elements in G. This list provides the "enumeration" of the group. Note that there are functions in Hap which assume that elts[1] is the identity element of G. appendToElts(g) a function that appends the group element g to .elts. This is not documented in Hap 1.8.6 but seems to be required for infinite groups. This requirement might vanish in some later version of Hap [G. Ellis, private communication]. dimension(k), a function which returns the ZG-rank of the Module M_k boundary(k,j), a function which returns the image in M_{k-1} of the jth free generator of M_k. Note that negative j are valid as input as well. In this case the additive inverse of the boundary of the jth generator is returned homotopy(k,[i,g]) a function which returns the image in M_{k+1}, under a contracting homotopy M_k \to M_{k+1}, of the element [[i,g]] in M_k. The value of this might be fail. However, currently (version 1.8.4) some Hap functions assume that homotopy is a function without testing. properties, a list of pairs ["name","value"] "name" is a string and value is anything (boolean, number, string...). Every HapResolution (regardless of representation) has to have ["type","resolution"], ["length",length] where length is the length of the resolution and ["characteristic",char]. Currently (Hap 1.8.6), length must not be infinity. The values of these properties can be tested using the Hap function EvaluateProperty(resolution,propertyname). Note that making HapResolutions immutable will make the .elts component immutable. As this lookup table might change during calculations, we do not recommend using immutable resolutions (in any representation).

The HapLargeGroupResolutionRep Representation In this sub-representation of the standard representation, the module elements in this resolution are lists of groupring elements. So the lookup table .elts is not used as long as no conversion to standard representation takes place. In addition to the components of a HapResolution, a resolution in large group representation has the following components: boundary2(resolution,term,gen), a function that returns the boundary of the genth generator of the termth module. groupring the group ring of the resolution resolution. dimension2(resolution,term) a function that returns the dimension of the termth module of the resolution resolution. The effort of having two versions of boundary and dimension is necessary to keep the structure compatible with the usual Hap resolution.
Accessing and Manipulating Resolutions
Representation-Independent Access Methods All methods listed below take a HapResolution in any representation. If the other arguments are compatible with the representation of the resolution, the returned value will be in the form defined by this representation. If the other arguments are in a different representation, &GAP;s method selection is used via TryNextMethod() to find an applicable method (a suitable representation).

The idea behind this is that the results of computations have the same form as the input. And as all representations are sub-representations of the HapResolutionRep representation, input which is compatible with the HapResolutionRep representation is always valid.

Every new representation must support the functions of this section. filter Finds the sub-representation of HapResolutionRep for which letter is a valid letter of the termth module of resolution. Note that resolution automatically is in some sub-representation of HapResolutionRep.This is mainly meant for debugging. filter Finds the sub-representation of HapResolutionRep for which word is a valid word of the termth module of resolution. Note that resolution automatically is in some sub-representation of HapResolutionRep. This is mainly meant for debugging. positive integer This returns the position of the group element g in the enumeration of the group of resolution. The NC version does not check if g really is an element of the group of resolution. boolean Returns true if the nth element of the group of resolution is known. group element or fail Returns nth element of the group of resolution. If the nth element is not known, fail is returned. positive integer or group element, depending on the type of x and y If x and y are given in standard representation (i.e. as integers), this returns the position of the product of the group elements represented by the positive integers x and x.

If x and y are given in any other representation, the returned group element will also be represented in this way. A letter Multiplies the letter letter with the group element g and returns the result. If resolution is in standard representation, g has to be an integer and letter has to be a pair of integer. If resolution is in any other representation, letter and g can be in a form compatible with that representation or in the standard form (in the latter case, the returned value will also have standard form). A word Multiplies the word word with the group element g and returns the result. If resolution is in standard representation, g has to be an integer and word has to be a list of pairs of integers. If resolution is in any other representation, word and g can be in a form compatible with that representation or in the standard form (in the latter case, the returned value will also have standard form). free ZG word (in the same representation as letter) Calculates the boundary of the letter (word of length 1) letter of the termth module of resolution.

The returned value is a word of the term-1st module and comes in the same representation as letter. free ZG word (in the same representation as letter) Calculates the boundary of the word word of the termth module of resolution.

The returned value is a word of the term-1st module and comes in the same representation as word.

Converting Between Representations Four methods are provided to convert letters and words from standard representation to any other representation and back again. letter in the representation of resolution Converts the letter letter in standard representation to the representation of resolution. The NC version does not check whether letter really is a letter in standard representation. word in the representation of resolution Converts the word word in standard representation to the representation of resolution. The NC version does not check whether word is a valid word in standard representation. letter in standard representation Converts the letter letter in the representation of resolution to the standard representation. The NC version does not check whether letter is a valid letter of resolution. word in standard representation Converts the word word in the representation of resolution to the standard representation. The NC version does not check whether word is a valid word of resolution.
Special Methods for HapResolutionRep Some methods explicitely require the input to be in the standard representation (HapResolutionRep). Two of these test if a word/letter is really in standard representation, the other ones are non-check versions of the universal methods. boolean Checks if letter is an valid letter (word of length 1) in standard representation of the termth module of resolution. boolean Check if word is a valid word in large standard representation of the termth module in resolution. positive integer Given positive integers x and y, this returns the position of the product of the group elements represented by the positive integers x and x. This assumes that all input is in standard representation and does not check the input. A letter in standard representation Multiplies the letter letter with the group element represented by the positive integer g and returns the result. The input is assumed to be in HapResolutionRep and is not checked. A letter in standard representation Multiplies the word word with the group element represented by the positive integer g and returns the result. The input is assumed to be in HapResolutionRep and is not checked. free ZG word in standard representation Calculates the boundary of the letter (word of length 1) letter of the termth module of resolution. The input is assumed to be in standard representation and not checked. free ZG word in standard representation Calculates the boundary of the word word of the termth module of resolution. The input is assumed to be in standard representation and not checked.
<#Include SYSTEM "./resolutionAccess_GroupRing.xml">
Contracting Homotopies <#Include SYSTEM "./contraction.xml"> hapcryst-0.2.0/doc/chapInd_mj.html0000644000175100017510000002674715160525022016461 0ustar runnerrunner GAP (HAPcryst) - Index
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

Index

action of crystallographic groups 1.1-1
BasisChangeAffineMatOnRight 2.2-2
BisectorInequalityFromPointPair 2.3-3
BoundaryOfFreeZGLetter B.1-9
BoundaryOfFreeZGLetter_LargeGroupRep B.4-11
BoundaryOfFreeZGLetterNC B.3-6
BoundaryOfFreeZGLetterNC_LargeGroupRep B.4-11
BoundaryOfFreeZGWord B.1-10
BoundaryOfFreeZGWord_LargeGroupRep B.4-12
BoundaryOfFreeZGWordNC B.3-7
BoundaryOfGenerator_LargeGroupRep B.4-10
BoundaryOfGeneratorNC_LargeGroupRep B.4-10
ConvertLetterToStandardRep B.2-3
ConvertLetterToStandardRepNC B.2-3
ConvertStandardLetter B.2-1
ConvertStandardLetterNC B.2-1
ConvertStandardWord B.2-2
ConvertStandardWordNC B.2-2
ConvertWordToStandardRep B.2-4
ConvertWordToStandardRepNC B.2-4
DimensionSquareMat 2.1-4
FaceLatticeAndBoundaryBieberbachGroup 4.2-2
FundamentalDomainBieberbachGroup 4.1-2
FundamentalDomainFromGeneralPointAndOrbitPartGeometric 4.1-3
FundamentalDomainStandardSpaceGroup 4.1-1
GeneratorsOfModuleOfResolution_LargeGroupRep B.4-9
GramianOfAverageScalarProductFromFiniteMatrixGroup 2.3-1
GroupElementFromPosition B.1-5
GroupRingOfResolution B.4-1
ineqThreshold 4.1-2
InfoHAPcryst 1.3-1
installation 1.2
IsFreeZGLetter B.3-1
IsFreeZGLetter_LargeGroupRep B.4-5
IsFreeZGLetterNoTermCheck_LargeGroupRep B.4-3
IsFreeZGWord B.3-2
IsFreeZGWord_LargeGroupRep B.4-6
IsFreeZGWordNoTermCheck_LargeGroupRep B.4-4
IsFundamentalDomainBieberbachGroup 4.1-5
IsFundamentalDomainStandardSpaceGroup 4.1-4
IsSquareMat 2.1-3
IsValidGroupInt B.1-4
LinearPartOfAffineMatOnRight 2.2-1
MultiplyFreeZGLetterWithGroupElt B.1-7
MultiplyFreeZGLetterWithGroupElt_LargeGroupRep B.4-7
MultiplyFreeZGLetterWithGroupEltNC B.3-4
MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep B.4-7
MultiplyFreeZGWordWithGroupElt B.1-8
MultiplyFreeZGWordWithGroupElt_LargeGroupRep B.4-8
MultiplyFreeZGWordWithGroupEltNC B.3-5
MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep B.4-8
MultiplyGroupElts B.1-6
MultiplyGroupElts_LargeGroupRep B.4-2
MultiplyGroupEltsNC B.3-3
MultiplyGroupEltsNC_LargeGroupRep B.4-2
OrbitPartAndRepresentativesInFacesStandardSpaceGroup 3.1-5
OrbitPartInFacesStandardSpaceGroup 3.1-4
OrbitPartInVertexSetsStandardSpaceGroup 3.1-3
OrbitStabilizerInUnitCubeOnRight 3.1-1
OrbitStabilizerInUnitCubeOnRightOnSets 3.1-2
PartialContractingHomotopyLookup C.1-2
PartialContractingHomotopyLookupNC C.1-2
PointGroupRepresentatives 2.4-1
polymake 1.2-1
PositionInGroupOfResolution B.1-3
PositionInGroupOfResolutionNC B.1-3
RelativePositionPointAndPolygon 2.3-5
RepresentativeActionOnRightOnSets 3.1-7
ResolutionBieberbachGroup 4.2-1
ResolutionFromFLandBoundary 4.2-3
ResolutionOfContractingHomotopy C.1-1
ShiftedOrbitPart 3.1-9
SignRat 2.1-1
StabilizerOnSetsStandardSpaceGroup 3.1-6
StrongestValidRepresentationForLetter B.1-1
StrongestValidRepresentationForWord B.1-2
TranslationOnRightFromVector 2.2-3
TranslationsToBox 3.1-11
TranslationsToOneCubeAroundCenter 3.1-10
VectorModOne 2.1-2
WhichSideOfHyperplane 2.3-4
WhichSideOfHyperplaneNC 2.3-4

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/chap2_mj.html0000644000175100017510000004501215160525022016072 0ustar runnerrunner GAP (HAPcryst) - Chapter 2: Bits and Pieces
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

2 Bits and Pieces

This chapter contains a few very basic functions which are needed for space group calculations and were missing in standard GAP.

2.1 Matrices and Vectors

2.1-1 SignRat
‣ SignRat( x )( method )

Returns: sign of the rational number x (Standard GAP currently only has SignInt).

2.1-2 VectorModOne
‣ VectorModOne( v )( method )

Returns: Rational vector of the same length with enties in \([0,1)\)

For a rational vector v, this returns the vector with all entries taken "mod 1".

gap> SignRat((-4)/(-2));
1
gap> SignRat(9/(-2));
-1
gap> VectorModOne([1/10,100/9,5/6,6/5]);
[ 1/10, 1/9, 5/6, 1/5 ]

2.1-3 IsSquareMat
‣ IsSquareMat( matrix )( method )

Returns: true if matrix is a square matrix and false otherwise.

2.1-4 DimensionSquareMat
‣ DimensionSquareMat( matrix )( method )

Returns: Number of lines in the matrix matrix if it is square and fail otherwise

gap> m:=[[1,2,3],[4,5,6],[9,6,12]];
[ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 9, 6, 12 ] ]
gap> IsSquareMat(m);
true
gap> DimensionSquareMat(m);
3
gap> DimensionSquareMat([[1,2],[1,2,3]]);
fail

Affine mappings of \(n\) dimensional space are often written as a pair \((A,v)\) where \(A\) is a linear mapping and \(v\) is a vector. GAP represents affine mappings by \(n+1\) times \(n+1\) matrices \(M\) which satisfy \(M_{{n+1,n+1}}=1\) and \(M_{{i,n+1}}=0\) for all \(1\leq i \leq n\).

An affine matrix acts on an \(n\) dimensional space which is written as a space of \(n+1\) tuples with \(n+1\)st entry \(1\). Here we give two functions to handle these affine matrices.

2.2 Affine Matrices OnRight

2.2-1 LinearPartOfAffineMatOnRight
‣ LinearPartOfAffineMatOnRight( mat )( method )

Returns: the linear part of the affine matrix mat. That is, everything except for the last row and column.

2.2-2 BasisChangeAffineMatOnRight
‣ BasisChangeAffineMatOnRight( transform, mat )( method )

Returns: affine matrix with same dimensions as mat

A basis change transform of an \(n\) dimensional space induces a transformation on affine mappings on this space. If mat is a affine matrix (in particular, it is \((n+1)\times (n+1)\)), this method returns the image of mat under the basis transformation induced by transform.

gap> c:=[[0,1],[1,0]];
[ [ 0, 1 ], [ 1, 0 ] ]
gap> m:=[[1/2,0,0],[0,2/3,0],[1,0,1]];
[ [ 1/2, 0, 0 ], [ 0, 2/3, 0 ], [ 1, 0, 1 ] ]
gap> BasisChangeAffineMatOnRight(c,m);
[ [ 2/3, 0, 0 ], [ 0, 1/2, 0 ], [ 0, 1, 1 ] ]

2.2-3 TranslationOnRightFromVector
‣ TranslationOnRightFromVector( v )( method )

Returns: Affine matrix

Given a vector v with \(n\) entries, this method returns a \((n+1)\times (n+1)\) matrix which corresponds to the affine translation defined by v.

gap> m:=TranslationOnRightFromVector([1,2,3]);;
gap> Display(m);
[ [  1,  0,  0,  0 ],
  [  0,  1,  0,  0 ],
  [  0,  0,  1,  0 ],
  [  1,  2,  3,  1 ] ]
gap> LinearPartOfAffineMatOnRight(m);
[ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ]
gap> BasisChangeAffineMatOnRight([[3,2,1],[0,1,0],[0,0,1]],m);
[ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 3, 4, 4, 1 ] ]

2.3 Geometry

2.3-1 GramianOfAverageScalarProductFromFiniteMatrixGroup
‣ GramianOfAverageScalarProductFromFiniteMatrixGroup( G )( method )

Returns: Symmetric positive definite matrix

For a finite matrix group G, the gramian matrix of the average scalar product is returned. This is the sum over all \(gg^t\) with \(g\in G\) (actually it is enough to take a generating set). The group G is orthogonal with respect to the scalar product induced by the returned matrix.

2.3-2 Inequalities

Inequalities are represented in the same way they are represented in polymaking. The vector \((v_0,\ldots,v_n)\) represents the inequality \(0\leq v_0+v_1 x_1+\ldots + v_n x_n\).

2.3-3 BisectorInequalityFromPointPair
‣ BisectorInequalityFromPointPair( v1, v2[, gram] )( method )

Returns: vector of length Length(v1)+1

Calculates the inequality defining the half-space containing v1 such that v1-v2 is perpendicular on the bounding hyperplane. And (v1-v2)/2 is contained in the bounding hyperplane.
If the matrix gram is given, it is used as the gramian matrix. Otherwiese, the standard scalar product is used. It is not checked if gram is positive definite or symmetric.

2.3-4 WhichSideOfHyperplane
‣ WhichSideOfHyperplane( v, ineq )( method )
‣ WhichSideOfHyperplaneNC( v, ineq )( method )

Returns: -1 (below) 0 (in) or 1 (above).

Let v be a vector of length \(n\) and ineq an inequality represented by a vector of length \(n+1\). Then WhichSideOfHyperplane(v, ineq) returns 1 if v is a solution of the inequality but not the equation given by ineq, it returns 0 if v is a solution to the equation and -1 if it is not a solution of the inequality ineq.

The NC version does not test the input for correctness.

gap> BisectorInequalityFromPointPair([0,0],[1,0]);
[ 1, -2, 0 ]
gap> ineq:=BisectorInequalityFromPointPair([0,0],[1,0],[[5,4],[4,5]]);
[ 5, -10, -8 ]
gap> ineq{[2,3]}*[1/2,0];
-5
gap> WhichSideOfHyperplane([0,0],ineq);
1
gap> WhichSideOfHyperplane([1/2,0],ineq);
0

2.3-5 RelativePositionPointAndPolygon
‣ RelativePositionPointAndPolygon( point, poly )( operation )

Returns: one of "VERTEX", "FACET", "OUTSIDE", "INSIDE"

Let poly be a PolymakeObject and point a vector. If point is a vertex of poly, the string "VERTEX" is returned. If point lies inside poly, "INSIDE" is returned and if it lies in a facet, "FACET" is returned and if point does not lie inside poly, the function returns "OUTSIDE".

2.4 Space Groups

2.4-1 PointGroupRepresentatives
‣ PointGroupRepresentatives( group )( attribute )

Returns: list of matrices

Given an AffineCrystGroupOnLeftOrRight group, this returns a list of representatives of the point group of group. That is, a system of representatives for the factor group modulo translations. This is an attribute of AffineCrystGroupOnLeftOrRight

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/clean0000755000175100017510000000021515160525022014525 0ustar runnerrunner#!/bin/bash rm -f *.{css,aux,log,dvi,ps,pdf,bbl,ilg,ind,idx,out,html,tex,pnr,txt,blg,toc,six,brf,js,lab} gapdocbib.xml.bib _*.xml title.xml hapcryst-0.2.0/doc/lefttoc.css0000644000175100017510000000047415160525022015676 0ustar runnerrunner/* leftmenu.css Frank LĂ¼beck */ /* Change default CSS to show section menu on left side */ body { padding-left: 28%; } body.chap0 { padding-left: 2%; } div.ChapSects div.ContSect:hover div.ContSSBlock { left: 15%; } div.ChapSects { left: 1%; width: 25%; } hapcryst-0.2.0/doc/chapInd.txt0000644000175100017510000000771515160525022015640 0ustar runnerrunner Index action of crystallographic groups 1.1-1 BasisChangeAffineMatOnRight 2.2-2 BisectorInequalityFromPointPair 2.3-3 BoundaryOfFreeZGLetter B.1-9 BoundaryOfFreeZGLetter_LargeGroupRep B.4-11 BoundaryOfFreeZGLetterNC B.3-6 BoundaryOfFreeZGLetterNC_LargeGroupRep B.4-11 BoundaryOfFreeZGWord B.1-10 BoundaryOfFreeZGWord_LargeGroupRep B.4-12 BoundaryOfFreeZGWordNC B.3-7 BoundaryOfGenerator_LargeGroupRep B.4-10 BoundaryOfGeneratorNC_LargeGroupRep B.4-10 ConvertLetterToStandardRep B.2-3 ConvertLetterToStandardRepNC B.2-3 ConvertStandardLetter B.2-1 ConvertStandardLetterNC B.2-1 ConvertStandardWord B.2-2 ConvertStandardWordNC B.2-2 ConvertWordToStandardRep B.2-4 ConvertWordToStandardRepNC B.2-4 DimensionSquareMat 2.1-4 FaceLatticeAndBoundaryBieberbachGroup 4.2-2 FundamentalDomainBieberbachGroup 4.1-2 FundamentalDomainFromGeneralPointAndOrbitPartGeometric 4.1-3 FundamentalDomainStandardSpaceGroup 4.1-1 GeneratorsOfModuleOfResolution_LargeGroupRep B.4-9 GramianOfAverageScalarProductFromFiniteMatrixGroup 2.3-1 GroupElementFromPosition B.1-5 GroupRingOfResolution B.4-1 ineqThreshold 4.1-2 InfoHAPcryst 1.3-1 installation 1.2 IsFreeZGLetter B.3-1 IsFreeZGLetter_LargeGroupRep B.4-5 IsFreeZGLetterNoTermCheck_LargeGroupRep B.4-3 IsFreeZGWord B.3-2 IsFreeZGWord_LargeGroupRep B.4-6 IsFreeZGWordNoTermCheck_LargeGroupRep B.4-4 IsFundamentalDomainBieberbachGroup 4.1-5 IsFundamentalDomainStandardSpaceGroup 4.1-4 IsSquareMat 2.1-3 IsValidGroupInt B.1-4 LinearPartOfAffineMatOnRight 2.2-1 MultiplyFreeZGLetterWithGroupElt B.1-7 MultiplyFreeZGLetterWithGroupElt_LargeGroupRep B.4-7 MultiplyFreeZGLetterWithGroupEltNC B.3-4 MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep B.4-7 MultiplyFreeZGWordWithGroupElt B.1-8 MultiplyFreeZGWordWithGroupElt_LargeGroupRep B.4-8 MultiplyFreeZGWordWithGroupEltNC B.3-5 MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep B.4-8 MultiplyGroupElts B.1-6 MultiplyGroupElts_LargeGroupRep B.4-2 MultiplyGroupEltsNC B.3-3 MultiplyGroupEltsNC_LargeGroupRep B.4-2 OrbitPartAndRepresentativesInFacesStandardSpaceGroup 3.1-5 OrbitPartInFacesStandardSpaceGroup 3.1-4 OrbitPartInVertexSetsStandardSpaceGroup 3.1-3 OrbitStabilizerInUnitCubeOnRight 3.1-1 OrbitStabilizerInUnitCubeOnRightOnSets 3.1-2 PartialContractingHomotopyLookup C.1-2 PartialContractingHomotopyLookupNC C.1-2 PointGroupRepresentatives 2.4-1 polymake 1.2-1 PositionInGroupOfResolution B.1-3 PositionInGroupOfResolutionNC B.1-3 RelativePositionPointAndPolygon 2.3-5 RepresentativeActionOnRightOnSets 3.1-7 ResolutionBieberbachGroup 4.2-1 ResolutionFromFLandBoundary 4.2-3 ResolutionOfContractingHomotopy C.1-1 ShiftedOrbitPart 3.1-9 SignRat 2.1-1 StabilizerOnSetsStandardSpaceGroup 3.1-6 StrongestValidRepresentationForLetter B.1-1 StrongestValidRepresentationForWord B.1-2 TranslationOnRightFromVector 2.2-3 TranslationsToBox 3.1-11 TranslationsToOneCubeAroundCenter 3.1-10 VectorModOne 2.1-2 WhichSideOfHyperplane 2.3-4 WhichSideOfHyperplaneNC 2.3-4 ------------------------------------------------------- hapcryst-0.2.0/doc/chapBib.html0000644000175100017510000000522515160525022015741 0ustar runnerrunner GAP (HAPcryst) - References
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

References

[EGN] Eick, B., Gahler, F. and Nickel, W., cryst, {https://www.gap-system.org/Packages/cryst.html}.

[Ell] Ellis, G., HAP, {http://hamilton.nuigalway.ie/Hap/www/}.

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/chapB.html0000644000175100017510000011430015160525022015421 0ustar runnerrunner GAP (HAPcryst) - Appendix B: Accessing and Manipulating Resolutions
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

B Accessing and Manipulating Resolutions

B Accessing and Manipulating Resolutions

B.1 Representation-Independent Access Methods

All methods listed below take a HapResolution in any representation. If the other arguments are compatible with the representation of the resolution, the returned value will be in the form defined by this representation. If the other arguments are in a different representation, GAPs method selection is used via TryNextMethod() to find an applicable method (a suitable representation).

The idea behind this is that the results of computations have the same form as the input. And as all representations are sub-representations of the HapResolutionRep representation, input which is compatible with the HapResolutionRep representation is always valid.

Every new representation must support the functions of this section.

B.1-1 StrongestValidRepresentationForLetter
‣ StrongestValidRepresentationForLetter( resolution, term, letter )( method )

Returns: filter

Finds the sub-representation of HapResolutionRep for which letter is a valid letter of the termth module of resolution. Note that resolution automatically is in some sub-representation of HapResolutionRep.This is mainly meant for debugging.

B.1-2 StrongestValidRepresentationForWord
‣ StrongestValidRepresentationForWord( resolution, term, word )( method )

Returns: filter

Finds the sub-representation of HapResolutionRep for which word is a valid word of the termth module of resolution. Note that resolution automatically is in some sub-representation of HapResolutionRep. This is mainly meant for debugging.

B.1-3 PositionInGroupOfResolution
‣ PositionInGroupOfResolution( resolution, g )( method )
‣ PositionInGroupOfResolutionNC( resolution, g )( method )

Returns: positive integer

This returns the position of the group element g in the enumeration of the group of resolution. The NC version does not check if g really is an element of the group of resolution.

B.1-4 IsValidGroupInt
‣ IsValidGroupInt( resolution, n )( method )

Returns: boolean

Returns true if the nth element of the group of resolution is known.

B.1-5 GroupElementFromPosition
‣ GroupElementFromPosition( resolution, n )( method )

Returns: group element or fail

Returns nth element of the group of resolution. If the nth element is not known, fail is returned.

B.1-6 MultiplyGroupElts
‣ MultiplyGroupElts( resolution, x, y )( method )

Returns: positive integer or group element, depending on the type of x and y

If x and y are given in standard representation (i.e. as integers), this returns the position of the product of the group elements represented by the positive integers x and x.

If x and y are given in any other representation, the returned group element will also be represented in this way.

B.1-7 MultiplyFreeZGLetterWithGroupElt
‣ MultiplyFreeZGLetterWithGroupElt( resolution, letter, g )( method )

Returns: A letter

Multiplies the letter letter with the group element g and returns the result. If resolution is in standard representation, g has to be an integer and letter has to be a pair of integer. If resolution is in any other representation, letter and g can be in a form compatible with that representation or in the standard form (in the latter case, the returned value will also have standard form).

B.1-8 MultiplyFreeZGWordWithGroupElt
‣ MultiplyFreeZGWordWithGroupElt( resolution, word, g )( method )

Returns: A word

Multiplies the word word with the group element g and returns the result. If resolution is in standard representation, g has to be an integer and word has to be a list of pairs of integers. If resolution is in any other representation, word and g can be in a form compatible with that representation or in the standard form (in the latter case, the returned value will also have standard form).

B.1-9 BoundaryOfFreeZGLetter
‣ BoundaryOfFreeZGLetter( resolution, term, letter )( method )

Returns: free ZG word (in the same representation as letter)

Calculates the boundary of the letter (word of length 1) letter of the termth module of resolution.

The returned value is a word of the term-1st module and comes in the same representation as letter.

B.1-10 BoundaryOfFreeZGWord
‣ BoundaryOfFreeZGWord( resolution, term, word )( method )

Returns: free ZG word (in the same representation as letter)

Calculates the boundary of the word word of the termth module of resolution.

The returned value is a word of the term-1st module and comes in the same representation as word.

B.2 Converting Between Representations

Four methods are provided to convert letters and words from standard representation to any other representation and back again.

B.2-1 ConvertStandardLetter
‣ ConvertStandardLetter( resolution, term, letter )( method )
‣ ConvertStandardLetterNC( resolution, term, letter )( method )

Returns: letter in the representation of resolution

Converts the letter letter in standard representation to the representation of resolution. The NC version does not check whether letter really is a letter in standard representation.

B.2-2 ConvertStandardWord
‣ ConvertStandardWord( resolution, term, word )( method )
‣ ConvertStandardWordNC( resolution, term, word )( method )

Returns: word in the representation of resolution

Converts the word word in standard representation to the representation of resolution. The NC version does not check whether word is a valid word in standard representation.

B.2-3 ConvertLetterToStandardRep
‣ ConvertLetterToStandardRep( resolution, term, letter )( method )
‣ ConvertLetterToStandardRepNC( resolution, term, letter )( method )

Returns: letter in standard representation

Converts the letter letter in the representation of resolution to the standard representation. The NC version does not check whether letter is a valid letter of resolution.

B.2-4 ConvertWordToStandardRep
‣ ConvertWordToStandardRep( resolution, term, word )( method )
‣ ConvertWordToStandardRepNC( resolution, term, word )( method )

Returns: word in standard representation

Converts the word word in the representation of resolution to the standard representation. The NC version does not check whether word is a valid word of resolution.

B.3 Special Methods for HapResolutionRep

Some methods explicitely require the input to be in the standard representation (HapResolutionRep). Two of these test if a word/letter is really in standard representation, the other ones are non-check versions of the universal methods.

B.3-1 IsFreeZGLetter
‣ IsFreeZGLetter( resolution, term, letter )( method )

Returns: boolean

Checks if letter is an valid letter (word of length 1) in standard representation of the termth module of resolution.

B.3-2 IsFreeZGWord
‣ IsFreeZGWord( resolution, term, word )( method )

Returns: boolean

Check if word is a valid word in large standard representation of the termth module in resolution.

B.3-3 MultiplyGroupEltsNC
‣ MultiplyGroupEltsNC( resolution, x, y )( method )

Returns: positive integer

Given positive integers x and y, this returns the position of the product of the group elements represented by the positive integers x and x. This assumes that all input is in standard representation and does not check the input.

B.3-4 MultiplyFreeZGLetterWithGroupEltNC
‣ MultiplyFreeZGLetterWithGroupEltNC( resolution, letter, g )( method )

Returns: A letter in standard representation

Multiplies the letter letter with the group element represented by the positive integer g and returns the result. The input is assumed to be in HapResolutionRep and is not checked.

B.3-5 MultiplyFreeZGWordWithGroupEltNC
‣ MultiplyFreeZGWordWithGroupEltNC( resolution, word, g )( method )

Returns: A letter in standard representation

Multiplies the word word with the group element represented by the positive integer g and returns the result. The input is assumed to be in HapResolutionRep and is not checked.

B.3-6 BoundaryOfFreeZGLetterNC
‣ BoundaryOfFreeZGLetterNC( resolution, term, letter )( method )

Returns: free ZG word in standard representation

Calculates the boundary of the letter (word of length 1) letter of the termth module of resolution. The input is assumed to be in standard representation and not checked.

B.3-7 BoundaryOfFreeZGWordNC
‣ BoundaryOfFreeZGWordNC( resolution, term, word )( method )

Returns: free ZG word in standard representation

Calculates the boundary of the word word of the termth module of resolution. The input is assumed to be in standard representation and not checked.

B.4 The HapLargeGroupResolutionRep Representation

The large group representation has one additional component called groupring. Elements of the modules in a resolution are represented by lists of group ring elements. The length of the list corresponds to the dimension of the free module.

All methods for the generic representation do also work for the large group representation. Some of them are wrappers for special methods which do only work for this representation. The following list only contains the methods which are not already present in the generic representation.

Note that the input or the output of these functions does not comply with the standard representation.

B.4-1 GroupRingOfResolution
‣ GroupRingOfResolution( resolution )( method )

Returns: group ring

This returns the group ring of resolution. Note that by the way that group rings are handled in GAP, this is not equal to GroupRing(R,GroupOfResolution(resolution)) where R is the ring of the resolution.

B.4-2 MultiplyGroupElts_LargeGroupRep
‣ MultiplyGroupElts_LargeGroupRep( resolution, x, y )( method )
‣ MultiplyGroupEltsNC_LargeGroupRep( resolution, x, y )( method )

Returns: group element

Returns the product of x and y. The NC version does not check whether x and y are actually elements of the group of resolution.

B.4-3 IsFreeZGLetterNoTermCheck_LargeGroupRep
‣ IsFreeZGLetterNoTermCheck_LargeGroupRep( resolution, letter )( method )

Returns: boolean

Returns true if letter has the form of a letter (a module element with exactly one non-zero entry which has exactly one non-zero coefficient) a module of resolution in the HapLargeGroupResolution representation. Note that it is not tested if letter actually is a letter in any term of resolution

B.4-4 IsFreeZGWordNoTermCheck_LargeGroupRep
‣ IsFreeZGWordNoTermCheck_LargeGroupRep( resolution, word )( method )

Returns: boolean

Returns true if word has the form of a word of a module of resolution in the HapLargeGroupResolution representation. Note that it is not tested if word actually is a word in any term of resolution.

B.4-5 IsFreeZGLetter_LargeGroupRep
‣ IsFreeZGLetter_LargeGroupRep( resolution, term, letter )( method )

Returns: boolean

Returns true if and only if letter is a letter (a word of length 1) of the termth module of resolution in the hapLargeGroupResolution representation. I.e. it tests if letter is a module element with exactly one non-zero entry which has exactly one non-zero coefficient.

B.4-6 IsFreeZGWord_LargeGroupRep
‣ IsFreeZGWord_LargeGroupRep( resolution, term, word )( method )

Returns: boolean

Tests if word is an element of the termth module of resoultion.

B.4-7 MultiplyFreeZGLetterWithGroupElt_LargeGroupRep
‣ MultiplyFreeZGLetterWithGroupElt_LargeGroupRep( resolution, letter, g )( method )
‣ MultiplyFreeZGLetterWithGroupEltNC_LargeGroupRep( resolution, letter, g )( method )

Returns: free ZG letter in large group representation

Multiplies the letter letter with the group element g and returns the result. The NC version does not check whether g is an element of the group of resolution and letter can be a letter.

B.4-8 MultiplyFreeZGWordWithGroupElt_LargeGroupRep
‣ MultiplyFreeZGWordWithGroupElt_LargeGroupRep( resolution, word, g )( method )
‣ MultiplyFreeZGWordWithGroupEltNC_LargeGroupRep( resolution, word, g )( method )

Returns: free ZG word in large group representation

Multiplies the word word with the group element g and returns the result. The NC version does not check whether g is an element of the group of resolution and word can be a word.

B.4-9 GeneratorsOfModuleOfResolution_LargeGroupRep
‣ GeneratorsOfModuleOfResolution_LargeGroupRep( resolution, term )( method )

Returns: list of letters/words in large group representation

Returns a set of generators for the termth module of resolution. The returned value is a list of vectors of group ring elements.

B.4-10 BoundaryOfGenerator_LargeGroupRep
‣ BoundaryOfGenerator_LargeGroupRep( resolution, term, n )( method )
‣ BoundaryOfGeneratorNC_LargeGroupRep( resolution, term, n )( method )

Returns: free ZG word in the large group representation

Returns the boundary of the nth generator of the termth module of resolution as a word in the n-1st module (in large group representation). The NC version does not check whether there is a termth module and if it has at least n generators.

B.4-11 BoundaryOfFreeZGLetterNC_LargeGroupRep
‣ BoundaryOfFreeZGLetterNC_LargeGroupRep( resolution, term, letter )( method )
‣ BoundaryOfFreeZGLetter_LargeGroupRep( resolution, term, letter )( method )

Returns: free ZG word in large group representation

Calculates the boundary of the letter letter of the termth module of resolution in large group representation. The NC version does not check whether letter actually is a letter in the termth module.

B.4-12 BoundaryOfFreeZGWord_LargeGroupRep
‣ BoundaryOfFreeZGWord_LargeGroupRep( resolution, term, word )( method )

Returns: free ZG word in large group representation

Calculates the boundary of the element word of the termth module of resolution in large group representation. The NC version does not check whether word actually is a word in the termth module.

Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/chap0.txt0000644000175100017510000001234615160525022015261 0ustar runnerrunner  HAPcryst   A HAP extension for crystallographic groups  Version 0.2.0 24 March 2026 Marc Roeder Marc Roeder Email: mailto:roeder.marc@gmail.com ------------------------------------------------------- Copyright © 2007 Marc Röder. This package is distributed under the terms of the GNU General Public License version 2 or later (at your convenience). See the file LICENSE or https://www.gnu.org/copyleft/gpl.html ------------------------------------------------------- Acknowledgements This work was supported by Marie Curie Grant No. MTKD-CT-2006-042685 ------------------------------------------------------- Contents (HAPcryst) 1 Introduction 1.1 Abstract and Notation 1.1-1 The natural action of crystallographic groups 1.2 Requirements 1.2-1 Recommendation concerning polymake 1.3 Global Variables 1.3-1 InfoHAPcryst 2 Bits and Pieces 2.1 Matrices and Vectors 2.1-1 SignRat 2.1-2 VectorModOne 2.1-3 IsSquareMat 2.1-4 DimensionSquareMat 2.2 Affine Matrices OnRight 2.2-1 LinearPartOfAffineMatOnRight 2.2-2 BasisChangeAffineMatOnRight 2.2-3 TranslationOnRightFromVector 2.3 Geometry 2.3-1 GramianOfAverageScalarProductFromFiniteMatrixGroup 2.3-2 Inequalities 2.3-3 BisectorInequalityFromPointPair 2.3-4 WhichSideOfHyperplane 2.3-5 RelativePositionPointAndPolygon 2.4 Space Groups 2.4-1 PointGroupRepresentatives 3 Algorithms of Orbit-Stabilizer Type 3.1 Orbit Stabilizer for Crystallographic Groups 3.1-1 OrbitStabilizerInUnitCubeOnRight 3.1-2 OrbitStabilizerInUnitCubeOnRightOnSets 3.1-3 OrbitPartInVertexSetsStandardSpaceGroup 3.1-4 OrbitPartInFacesStandardSpaceGroup 3.1-5 OrbitPartAndRepresentativesInFacesStandardSpaceGroup 3.1-6 StabilizerOnSetsStandardSpaceGroup 3.1-7 RepresentativeActionOnRightOnSets 3.1-8 Getting other orbit parts 3.1-9 ShiftedOrbitPart 3.1-10 TranslationsToOneCubeAroundCenter 3.1-11 TranslationsToBox 4 Resolutions of Crystallographic Groups 4.1 Fundamental Domains 4.1-1 FundamentalDomainStandardSpaceGroup 4.1-2 FundamentalDomainBieberbachGroup 4.1-3 FundamentalDomainFromGeneralPointAndOrbitPartGeometric 4.1-4 IsFundamentalDomainStandardSpaceGroup 4.1-5 IsFundamentalDomainBieberbachGroup 4.2 Face Lattice and Resolution 4.2-1 ResolutionBieberbachGroup 4.2-2 FaceLatticeAndBoundaryBieberbachGroup 4.2-3 ResolutionFromFLandBoundary A Resolutions in Hap A.1 The Standard Representation HapResolutionRep A.2 The HapLargeGroupResolutionRep Representation B Accessing and Manipulating Resolutions B.1 Representation-Independent Access Methods B.1-1 StrongestValidRepresentationForLetter B.1-2 StrongestValidRepresentationForWord B.1-3 PositionInGroupOfResolution B.1-4 IsValidGroupInt B.1-5 GroupElementFromPosition B.1-6 MultiplyGroupElts B.1-7 MultiplyFreeZGLetterWithGroupElt B.1-8 MultiplyFreeZGWordWithGroupElt B.1-9 BoundaryOfFreeZGLetter B.1-10 BoundaryOfFreeZGWord B.2 Converting Between Representations B.2-1 ConvertStandardLetter B.2-2 ConvertStandardWord B.2-3 ConvertLetterToStandardRep B.2-4 ConvertWordToStandardRep B.3 Special Methods for HapResolutionRep B.3-1 IsFreeZGLetter B.3-2 IsFreeZGWord B.3-3 MultiplyGroupEltsNC B.3-4 MultiplyFreeZGLetterWithGroupEltNC B.3-5 MultiplyFreeZGWordWithGroupEltNC B.3-6 BoundaryOfFreeZGLetterNC B.3-7 BoundaryOfFreeZGWordNC B.4 The HapLargeGroupResolutionRep Representation B.4-1 GroupRingOfResolution B.4-2 MultiplyGroupElts_LargeGroupRep B.4-3 IsFreeZGLetterNoTermCheck_LargeGroupRep B.4-4 IsFreeZGWordNoTermCheck_LargeGroupRep B.4-5 IsFreeZGLetter_LargeGroupRep B.4-6 IsFreeZGWord_LargeGroupRep B.4-7 MultiplyFreeZGLetterWithGroupElt_LargeGroupRep B.4-8 MultiplyFreeZGWordWithGroupElt_LargeGroupRep B.4-9 GeneratorsOfModuleOfResolution_LargeGroupRep B.4-10 BoundaryOfGenerator_LargeGroupRep B.4-11 BoundaryOfFreeZGLetterNC_LargeGroupRep B.4-12 BoundaryOfFreeZGWord_LargeGroupRep C Contracting Homotopies C.1 The PartialContractingHomotopy Data Type C.1-1 ResolutionOfContractingHomotopy C.1-2 PartialContractingHomotopyLookup  hapcryst-0.2.0/doc/nocolorprompt.css0000644000175100017510000000031315160525022017143 0ustar runnerrunner /* colors for ColorPrompt like examples */ span.GAPprompt { color: #000000; font-weight: normal; } span.GAPbrkprompt { color: #000000; font-weight: normal; } span.GAPinput { color: #000000; } hapcryst-0.2.0/doc/chap2.txt0000644000175100017510000002340315160525022015257 0ustar runnerrunner 2 Bits and Pieces This chapter contains a few very basic functions which are needed for space group calculations and were missing in standard GAP. 2.1 Matrices and Vectors 2.1-1 SignRat SignRat( x )  method Returns: sign of the rational number x (Standard GAP currently only has SignInt). 2.1-2 VectorModOne VectorModOne( v )  method Returns: Rational vector of the same length with enties in [0,1) For a rational vector v, this returns the vector with all entries taken "mod 1".  Example  gap> SignRat((-4)/(-2)); 1 gap> SignRat(9/(-2)); -1 gap> VectorModOne([1/10,100/9,5/6,6/5]); [ 1/10, 1/9, 5/6, 1/5 ]  2.1-3 IsSquareMat IsSquareMat( matrix )  method Returns: true if matrix is a square matrix and false otherwise. 2.1-4 DimensionSquareMat DimensionSquareMat( matrix )  method Returns: Number of lines in the matrix matrix if it is square and fail otherwise  Example  gap> m:=[[1,2,3],[4,5,6],[9,6,12]]; [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 9, 6, 12 ] ] gap> IsSquareMat(m); true gap> DimensionSquareMat(m); 3 gap> DimensionSquareMat([[1,2],[1,2,3]]); fail  Affine mappings of n dimensional space are often written as a pair (A,v) where A is a linear mapping and v is a vector. GAP represents affine mappings by n+1 times n+1 matrices M which satisfy M_{n+1,n+1}=1 and M_{i,n+1}=0 for all 1≤ i ≤ n. An affine matrix acts on an n dimensional space which is written as a space of n+1 tuples with n+1st entry 1. Here we give two functions to handle these affine matrices. 2.2 Affine Matrices OnRight 2.2-1 LinearPartOfAffineMatOnRight LinearPartOfAffineMatOnRight( mat )  method Returns: the linear part of the affine matrix mat. That is, everything except for the last row and column. 2.2-2 BasisChangeAffineMatOnRight BasisChangeAffineMatOnRight( transform, mat )  method Returns: affine matrix with same dimensions as mat A basis change transform of an n dimensional space induces a transformation on affine mappings on this space. If mat is a affine matrix (in particular, it is (n+1)Ă— (n+1)), this method returns the image of mat under the basis transformation induced by transform.  Example  gap> c:=[[0,1],[1,0]]; [ [ 0, 1 ], [ 1, 0 ] ] gap> m:=[[1/2,0,0],[0,2/3,0],[1,0,1]]; [ [ 1/2, 0, 0 ], [ 0, 2/3, 0 ], [ 1, 0, 1 ] ] gap> BasisChangeAffineMatOnRight(c,m); [ [ 2/3, 0, 0 ], [ 0, 1/2, 0 ], [ 0, 1, 1 ] ]  2.2-3 TranslationOnRightFromVector TranslationOnRightFromVector( v )  method Returns: Affine matrix Given a vector v with n entries, this method returns a (n+1)Ă— (n+1) matrix which corresponds to the affine translation defined by v.  Example  gap> m:=TranslationOnRightFromVector([1,2,3]);; gap> Display(m); [ [ 1, 0, 0, 0 ],  [ 0, 1, 0, 0 ],  [ 0, 0, 1, 0 ],  [ 1, 2, 3, 1 ] ] gap> LinearPartOfAffineMatOnRight(m); [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ] gap> BasisChangeAffineMatOnRight([[3,2,1],[0,1,0],[0,0,1]],m); [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 3, 4, 4, 1 ] ]  2.3 Geometry 2.3-1 GramianOfAverageScalarProductFromFiniteMatrixGroup GramianOfAverageScalarProductFromFiniteMatrixGroup( G )  method Returns: Symmetric positive definite matrix For a finite matrix group G, the gramian matrix of the average scalar product is returned. This is the sum over all gg^t with g∈ G (actually it is enough to take a generating set). The group G is orthogonal with respect to the scalar product induced by the returned matrix. 2.3-2 Inequalities Inequalities are represented in the same way they are represented in polymaking. The vector (v_0,...,v_n) represents the inequality 0≤ v_0+v_1 x_1+... + v_n x_n. 2.3-3 BisectorInequalityFromPointPair BisectorInequalityFromPointPair( v1, v2[, gram] )  method Returns: vector of length Length(v1)+1 Calculates the inequality defining the half-space containing v1 such that v1-v2 is perpendicular on the bounding hyperplane. And (v1-v2)/2 is contained in the bounding hyperplane. If the matrix gram is given, it is used as the gramian matrix. Otherwiese, the standard scalar product is used. It is not checked if gram is positive definite or symmetric. 2.3-4 WhichSideOfHyperplane WhichSideOfHyperplane( v, ineq )  method WhichSideOfHyperplaneNC( v, ineq )  method Returns: -1 (below) 0 (in) or 1 (above). Let v be a vector of length n and ineq an inequality represented by a vector of length n+1. Then WhichSideOfHyperplane(v, ineq) returns 1 if v is a solution of the inequality but not the equation given by ineq, it returns 0 if v is a solution to the equation and -1 if it is not a solution of the inequality ineq. The NC version does not test the input for correctness.  Example  gap> BisectorInequalityFromPointPair([0,0],[1,0]); [ 1, -2, 0 ] gap> ineq:=BisectorInequalityFromPointPair([0,0],[1,0],[[5,4],[4,5]]); [ 5, -10, -8 ] gap> ineq{[2,3]}*[1/2,0]; -5 gap> WhichSideOfHyperplane([0,0],ineq); 1 gap> WhichSideOfHyperplane([1/2,0],ineq); 0  2.3-5 RelativePositionPointAndPolygon RelativePositionPointAndPolygon( point, poly )  operation Returns: one of "VERTEX", "FACET", "OUTSIDE", "INSIDE" Let poly be a PolymakeObject and point a vector. If point is a vertex of poly, the string "VERTEX" is returned. If point lies inside poly, "INSIDE" is returned and if it lies in a facet, "FACET" is returned and if point does not lie inside poly, the function returns "OUTSIDE". 2.4 Space Groups 2.4-1 PointGroupRepresentatives PointGroupRepresentatives( group )  attribute Returns: list of matrices Given an AffineCrystGroupOnLeftOrRight group, this returns a list of representatives of the point group of group. That is, a system of representatives for the factor group modulo translations. This is an attribute of AffineCrystGroupOnLeftOrRight hapcryst-0.2.0/doc/_entities.xml0000644000175100017510000000006115160525022016221 0ustar runnerrunnerHAPcryst'> hapcryst-0.2.0/doc/manual.css0000644000175100017510000001575415160525022015522 0ustar runnerrunner/* manual.css Frank LĂ¼beck */ /* This is the default CSS style sheet for GAPDoc HTML manuals. */ /* basic settings, fonts, sizes, colors, ... */ body { position: relative; background: #ffffff; color: #000000; width: 70%; margin: 0pt; padding: 15pt; font-family: Helvetica,Verdana,Arial,sans-serif; text-align: justify; } /* no side toc on title page, bib and index */ body.chap0 { width: 95%; } body.chapBib { width: 95%; } body.chapInd { width: 95%; } h1 { font-size: 200%; } h2 { font-size: 160%; } h3 { font-size: 160%; } h4 { font-size: 130%; } h5 { font-size: 100%; } p.foot { font-size: 60%; font-style: normal; } a:link { color: #00008e; text-decoration: none; } a:visited { color: #00008e; text-decoration: none; } a:active { color: #000000; text-decoration: none; } a:hover { background: #eeeeee; } pre { font-family: "Courier New",Courier,monospace; font-size: 100%; color:#111111; } tt,code { font-family: "Courier New",Courier,monospace; font-size: 110%; color: #000000; } var { } /* general alignment classes */ .pcenter { text-align: center; } .pleft { text-align: left; } .pright { text-align: right; } /* layout for the definitions of functions, variables, ... */ div.func { background: #e0e0e0; margin: 0pt 0pt; } /* general and special table settings */ table { border-collapse: collapse; margin-left: auto; margin-right: auto; } td, th { border-style: none; } table.func { padding: 0pt 1ex; margin-left: 1ex; margin-right: 1ex; background: transparent; /* line-height: 1.1; */ width: 100%; } table.func td.tdright { padding-right: 2ex; } /* Example elements (for old converted manuals, now in div+pre */ table.example { background: #efefef; border-style: none; border-width: 0pt; padding: 0px; width: 100% } table.example td { border-style: none; border-width: 0pt; padding: 0ex 1ex; } /* becomes ... */ div.example { background: #efefef; padding: 0ex 1ex; /* overflow-x: auto; */ overflow: auto; } /* Links to chapters in all files at top and bottom. */ /* If there are too many chapters then use 'display: none' here. */ div.chlinktop { background: #dddddd; border-style: solid; border-width: thin; margin: 2px; text-align: center; } div.chlinktop a { margin: 3px; } div.chlinktop a:hover { background: #ffffff; } div.chlinkbot { background: #dddddd; border-style: solid; border-width: thin; margin: 2px; text-align: center; /* width: 100%; */ } div.chlinkbot a { margin: 3px; } span.chlink1 { } /* and this is for the "Top", "Prev", "Next" links */ div.chlinkprevnexttop { background: #dddddd; border-style: solid; border-width: thin; text-align: center; margin: 2px; } div.chlinkprevnexttop a:hover { background: #ffffff; } div.chlinkprevnextbot { background: #dddddd; border-style: solid; border-width: thin; text-align: center; margin: 2px; } div.chlinkprevnextbot a:hover { background: #ffffff; } /* table of contents, initially don't display subsections */ div.ContSSBlock { display: none; } div.ContSSBlock br { display: none; } /* format in separate lines */ span.tocline { display: block; width: 100%; } div.ContSSBlock a { display: block; } /* this is for the main table of contents */ div.ContChap { } div.ContChap div.ContSect:hover div.ContSSBlock { display: block; position: absolute; background: #eeeeee; border-style: solid; border-width: 1px 4px 4px 1px; border-color: #666666; padding-left: 0.5ex; color: #000000; left: 20%; width: 40%; z-index: 10000; } div.ContSSBlock a:hover { background: #ffffff; } /* and here for the side menu of contents in the chapter files */ div.ChapSects { } div.ChapSects a:hover { background: #eeeeee; } div.ChapSects a:hover { display: block; width: 100%; background: #eeeeee; color: #000000; } div.ChapSects div.ContSect:hover div.ContSSBlock { display: block; position: fixed; background: #eeeeee; border-style: solid; border-width: 1px 2px 2px 1px; border-color: #666666; padding-left: 0ex; padding-right: 0.5ex; color: #000000; left: 54%; width: 25%; z-index: 10000; } div.ChapSects div.ContSect:hover div.ContSSBlock a { display: block; margin-left: 3px; } div.ChapSects div.ContSect:hover div.ContSSBlock a:hover { display: block; background: #ffffff; } div.ContSect { text-align: left; margin-left: 1em; } div.ChapSects { position: fixed; left: 75%; font-size: 90%; overflow: auto; top: 10px; bottom: 0px; } /* Table elements */ table.GAPDocTable { border-collapse: collapse; border-style: none; border-color: black; } table.GAPDocTable td, table.GAPDocTable th { padding: 3pt; border-width: thin; border-style: solid; border-color: #555555; } caption.GAPDocTable { caption-side: bottom; width: 70%; margin-top: 1em; margin-left: auto; margin-right: auto; } td.tdleft { text-align: left; } table.GAPDocTablenoborder { border-collapse: collapse; border-style: none; border-color: black; } table.GAPDocTablenoborder td, table.GAPDocTable th { padding: 3pt; border-width: 0pt; border-style: solid; border-color: #555555; } caption.GAPDocTablenoborder { caption-side: bottom; width: 70%; margin-top: 1em; margin-left: auto; margin-right: auto; } td.tdleft { text-align: left; } td.tdright { text-align: right; } td.tdcenter { text-align: center; } /* Colors and fonts can be overwritten for some types of elements. */ /* Verb elements */ pre.normal { color: #000000; } /* Func-like elements and Ref to Func-like */ code.func { color: #000000; } /* K elements */ code.keyw { color: #770000; } /* F elements */ code.file { color: #8e4510; } /* C elements */ code.code { } /* Item elements */ code.i { } /* Button elements */ strong.button { } /* Headings */ span.Heading { } /* Arg elements */ var.Arg { color: #006600; } /* Example elements, is in tables, see above */ div.Example { } /* Package elements */ strong.pkg { } /* URL-like elements */ span.URL { } /* Mark elements */ strong.Mark { } /* Ref elements */ b.Ref { } span.Ref { } /* this contains the contents page */ div.contents { } /* this contains the index page */ div.index { } /* ignore some text for non-css layout */ span.nocss { display: none; } /* colors for ColorPrompt like examples */ span.GAPprompt { color: #000097; font-weight: normal; } span.GAPbrkprompt { color: #970000; font-weight: normal; } span.GAPinput { color: #970000; } /* Bib entries */ p.BibEntry { } span.BibKey { color: #005522; } span.BibKeyLink { } b.BibAuthor { } i.BibTitle { } i.BibBookTitle { } span.BibEditor { } span.BibJournal { } span.BibType { } span.BibPublisher { } span.BibSchool { } span.BibEdition { } span.BibVolume { } span.BibSeries { } span.BibNumber { } span.BibPages { } span.BibOrganization { } span.BibAddress { } span.BibYear { } span.BibPublisher { } span.BibNote { } span.BibHowpublished { } hapcryst-0.2.0/doc/chap4_mj.html0000644000175100017510000005762415160525022016110 0ustar runnerrunner GAP (HAPcryst) - Chapter 4: Resolutions of Crystallographic Groups
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

4 Resolutions of Crystallographic Groups

4.1 Fundamental Domains

Let \(S\) be a crystallographic group. A Fundamental domain is a closed convex set containing a system of representatives for the Orbits of \(S\) in its natural action on euclidian space.
There are two algorithms for calculating fundamental domains in HAPcryst. One uses the geometry and relies on having the standard rule for evaluating the scalar product (i.e. the gramian matrix is the identity). The other one is independent of the gramian matrix but does only work for Bieberbach groups, while the first ("geometric") algorithm works for arbitrary crystallographic groups given a point with trivial stabilizer.

4.1-1 FundamentalDomainStandardSpaceGroup
‣ FundamentalDomainStandardSpaceGroup( [v, ]G )( operation )

Returns: a PolymakeObject

Let G be an AffineCrystGroupOnRight and v a vector. A fundamental domain containing v is calculated and returned as a PolymakeObject. The vector v is used as the starting point for a Dirichlet-Voronoi construction. If no v is given, the origin is used as starting point if it has trivial stabiliser. Otherwise an error is cast.

gap> fd:=FundamentalDomainStandardSpaceGroup([1/2,0,1/5],SpaceGroup(3,9));
<polymake object>
gap> Polymake(fd,"N_VERTICES");
24
gap> fd:=FundamentalDomainStandardSpaceGroup(SpaceGroup(3,9));
<polymake object>
gap> Polymake(fd,"N_VERTICES");
8

4.1-2 FundamentalDomainBieberbachGroup
‣ FundamentalDomainBieberbachGroup( [v, ]G[, gram] )( operation )

Returns: a PolymakeObject

Given a starting vector v and a Bieberbach group G in standard form, this method calculates the Dirichlet domain with respect to v. If gram is not supplied, the average gramian matrix is used (see GramianOfAverageScalarProductFromFiniteMatrixGroup (2.3-1)). It is not tested if gram is symmetric and positive definite. It is also not tested, if the product defined by gram is invariant under the point group of G.

The behaviour of this function is influenced by the option ineqThreshold. The algorithm calculates approximations to a fundamental domain by iteratively adding inequalities. For an approximating polyhedron, every vertex is tested to find new inequalities. When all vertices have been considered or the number of new inequalities already found exceeds the value of ineqThreshold, a new approximating polyhedron in calculated. The default for ineqThreshold is 200. Roughly speaking, a large threshold means shifting work from polymake to GAP, a small one means more calls of (and work for) polymake.

If the value of InfoHAPcryst (1.3-1) is 2 or more, for each approximation the number of vertices of the approximation, the number of vertices that have to be considered during the calculation, the number of facets, and new inequalities is shown.

Note that the algorithm chooses vertices in random order and also writes inequalities for polymake in random order.

gap> a0:=[[ 1, 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0, 0 ], 
>     [ 0, 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 0 ], 
>     [ 0, 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, -1, -1, 0 ],
>     [ -1/2, 0, 0, 1/6, 0, 0, 1 ] 
>     ];;
gap> a1:=[[ 0, -1, 0, 0, 0, 0, 0 ],[ 0, 0, -1, 0, 0, 0, 0 ],
>         [ 1, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 0 ], 
>         [ 0, 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 1, 0 ],
>         [ 0, 0, 0, 0, 1/3, -1/3, 1 ] 
>        ];;
gap> trans:=List(Group((1,2,3,4,5,6)),g->
>           TranslationOnRightFromVector(Permuted([1,0,0,0,0,0],g)));;
gap> S:=AffineCrystGroupOnRight(Concatenation(trans,[a0,a1]));
<matrix group with 8 generators>
gap> SetInfoLevel(InfoHAPcryst,2);
gap> FundamentalDomainBieberbachGroup(S:ineqThreshold:=10);
#I  v: 104/104 f:15
#I  new: 201
#I  v: 961/961 f:58
#I  new: 20
#I  v: 1143/805 f:69
#I  new: 12
#I  v: 1059/555 f:64
#I  new: 15
#I  v: 328/109 f:33
#I  new: 12
#I  v: 336/58 f:32
#I  new: 0
<polymake object>
gap> FundamentalDomainBieberbachGroup(S:ineqThreshold:=1000);
#I  v: 104/104 f:15
#I  new: 149
#I  v: 635/635 f:41
#I  new: 115
#I  v: 336/183 f:32
#I  new: 0
#I  out of inequalities
<polymake object>

4.1-3 FundamentalDomainFromGeneralPointAndOrbitPartGeometric
‣ FundamentalDomainFromGeneralPointAndOrbitPartGeometric( v, orbit )( method )

Returns: a PolymakeObject

This uses an alternative algorithm based on geometric considerations. It is not used in any of the high-level methods. Let v be a vector and orbit a sufficiently large part of the orbit of v under a crystallographic group with standard- orthogonal point group (satisfying \(A^t=A^-1\)). A geometric algorithm is then used to calculate the Dirichlet domain with respect to v. This also works for crystallographic groups which are not Bieberbach. The point v has to have trivial stabilizer.
The intersection of the full orbit with the unit cube around v is sufficiently large.

gap> G:=SpaceGroup(3,9);;
gap> v:=[0,0,0];
[ 0, 0, 0 ]
gap> orbit:=OrbitStabilizerInUnitCubeOnRight(G,v).orbit;
[ [ 0, 0, 0 ], [ 0, 0, 1/2 ] ]
gap> fd:=FundamentalDomainFromGeneralPointAndOrbitPartGeometric(v,orbit);
<polymake object>
gap> Polymake(fd,"N_VERTICES");
8

4.1-4 IsFundamentalDomainStandardSpaceGroup
‣ IsFundamentalDomainStandardSpaceGroup( poly, G )( method )

Returns: true or false

This tests if a PolymakeObject poly is a fundamental domain for the affine crystallographic group G in standard form.
The function tests the following: First, does the orbit of any vertex of poly have a point inside poly (if this is the case, false is returned). Second: Is every facet of poly the image of a different facet under a group element which does not fix poly. If this is satisfied, true is returned.

4.1-5 IsFundamentalDomainBieberbachGroup
‣ IsFundamentalDomainBieberbachGroup( poly, G )( method )

Returns: true, false or fail

This tests if a PolymakeObject poly is a fundamental domain for the affine crystallographic group G in standard form and if this group is torsion free (ie a Bieberbach group)
It returns true if G is torsion free and poly is a fundamental domain for G. If poly is not a fundamental domain, false is returned regardless of the structure of G. And if G is not torsion free, the method returns fail. If G is polycyclic, torsion freeness is tested using a representation as pcp group. Otherwise the stabilisers of the faces of the fundamental domain poly are calculated (G is torsion free if and only if it all these stabilisers are trivial).

4.2 Face Lattice and Resolution

For Bieberbach groups (torsion free crystallographic groups), the following functions calcualte free resolutions. This calculation is done by finding a fundamental domain for the group. For a description of the HapResolution datatype, see the Hap data types documentation or the experimental datatypes documentation A

4.2-1 ResolutionBieberbachGroup
‣ ResolutionBieberbachGroup( G[, v] )( method )

Returns: a HAPresolution

Let G be a Bieberbach group given as an AffineCrystGroupOnRight and v a vector. Then a Dirichlet domain with respect to v is calculated using FundamentalDomainBieberbachGroup (4.1-2). From this domain, a resolution is calculated using FaceLatticeAndBoundaryBieberbachGroup (4.2-2) and ResolutionFromFLandBoundary (4.2-3). If v is not given, the origin is used.

gap> R:=ResolutionBieberbachGroup(SpaceGroup(3,9));
Resolution of length 3 in characteristic
0 for SpaceGroupOnRightBBNWZ( 3, 2, 2, 2, 2 ) .
No contracting homotopy available.

gap> List([0..3],Dimension(R));
[ 1, 3, 3, 1 ]
gap> R:=ResolutionBieberbachGroup(SpaceGroup(3,9),[1/2,0,0]);
Resolution of length 3 in characteristic
0 for SpaceGroupOnRightBBNWZ( 3, 2, 2, 2, 2 ) .
No contracting homotopy available.

gap> List([0..3],Dimension(R));
[ 6, 12, 7, 1 ]

4.2-2 FaceLatticeAndBoundaryBieberbachGroup
‣ FaceLatticeAndBoundaryBieberbachGroup( poly, group )( method )

Returns: Record with entries .hasse and .elts representing a part of the hasse diagram and a lookup table of group elements

Let group be a torsion free AffineCrystGroupOnRight (that is, a Bieberbach group). Given a PolymakeObject poly representing a fundamental domain for group, this method uses polymaking to calculate the face lattice of poly. From the set of faces, a system of representatives for group- orbits is chosen. For each representative, the boundary is then calculated. The list .elts contains elements of group (in fact, it is even a set). The structure of the returned list .hasse is as follows:

  • The \(i\)-th entry contains a system of representatives for the \(i-1\) dimensional faces of poly.

  • Each face is represented by a pair of lists [vertices,boundary]. The list of integers vertices represents the vertices of poly which are contained in this face. The enumeration is chosen such that an i in the list represents the \(i\)-th entry of the list Polymake(poly,"VERTICES");

  • The list boundary represents the boundary of the respective face. It is a list of pairs of integers [j,g]. The first entry lies between \(-n\) and \(n\), where \(n\) is the number of faces of dimension \(i-1\). This entry represents a face of dimension \(i-1\) (or its additive inverse as a module generator). The second entry g is the position of the matrix in .elts.

This representation is compatible with the representation of free \(\mathbb Z G\) modules in Hap and this method essentially calculates a free resolution of group. If the value of InfoHAPcryst (1.3-1) is 2 or more, additional information about the number of faces in every codimension, the number of orbits of the group on the free module generated by those faces, and the time it took to calculate the orbit decomposition is output.

gap> SetInfoLevel(InfoHAPcryst,2);
gap> G:=SpaceGroup(3,165);
SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 )
gap> fd:=FundamentalDomainBieberbachGroup(G);
<polymake object>
gap> fl:=FaceLatticeAndBoundaryBieberbachGroup(fd,G);;
#I  1(4/8): 0:00:00.004
#I  2(5/18): 0:00:00.000
#I  3(2/12): 0:00:00.000
#I  Face lattice done ( 0:00:00.004). Calculating boundary
#I  done ( 0:00:00.004) Reformating...
gap> RecNames(fl);
[ "hasse", "elts", "groupring" ]
gap> fl.groupring;
<free left module over Integers, and ring-with-one, with 10 generators>

4.2-3 ResolutionFromFLandBoundary
‣ ResolutionFromFLandBoundary( fl, group )( method )

Returns: Free resolution

If fl is the record output by FaceLatticeAndBoundaryBieberbachGroup (4.2-2) and group is the corresponding group, this function returns a HapResolution. Of course, fl has to be generated from a fundamental domain for group

gap> G:=SpaceGroup(3,165);
SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 )
gap> fd:=FundamentalDomainBieberbachGroup(G);
<polymake object>
gap> fl:=FaceLatticeAndBoundaryBieberbachGroup(fd,G);;
gap> ResolutionFromFLandBoundary(fl,G);
Resolution of length 3 in characteristic
0 for SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) .
No contracting homotopy available.

gap> ResolutionFromFLandBoundary(fl,G);
Resolution of length 3 in characteristic
0 for SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) .
No contracting homotopy available.

gap> List([0..4],Dimension(last));
[ 2, 5, 4, 1, 0 ]
Goto Chapter: Top 1 2 3 4 A B C Bib Ind

generated by GAPDoc2HTML

hapcryst-0.2.0/doc/manual.js0000644000175100017510000001011315160525022015326 0ustar runnerrunner/* manual.js Frank LĂ¼beck */ /* This file contains a few javascript functions which allow to switch between display styles for GAPDoc HTML manuals. If javascript is switched off in a browser or this file in not available in a manual directory, this is no problem. Users just cannot switch between several styles and don't see the corresponding button. A style with name mystyle can be added by providing two files (or only one of them). mystyle.js: Additional javascript code for the style, it is read in the HTML pages after this current file. The additional code may adjust the preprocessing function jscontent() with is called onload of a file. This is done by appending functions to jscontentfuncs (jscontentfuncs.push(newfunc);). Make sure, that your style is still usable without javascript. mystyle.css: CSS configuration, read after manual.css (so it can just reconfigure a few details, or overwrite everything). Then adjust chooser.html such that users can switch on and off mystyle. A user can change the preferred style permanently by using the [Style] link and choosing one. Or one can append '?GAPDocStyle=mystyle' to the URL when loading any file of the manual (so the style can be configured in the GAP user preferences). */ /* generic helper function */ function deleteCookie(nam) { document.cookie = nam+"=;Path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT"; } /* read a value from a "nam1=val1;nam2=val2;..." string (e.g., the search part of an URL or a cookie */ function valueString(str,nam) { var cs = str.split(";"); for (var i=0; i < cs.length; i++) { var pos = cs[i].search(nam+"="); if (pos > -1) { pos = cs[i].indexOf("="); return cs[i].slice(pos+1); } } return 0; } /* when a non-default style is chosen via URL or a cookie, then the cookie is reset and the styles .js and .css files are read */ function overwriteStyle() { /* style in URL? */ var style = valueString(window.location.search, "GAPDocStyle"); /* otherwise check cookie */ if (style == 0) style = valueString(document.cookie, "GAPDocStyle"); if (style == 0) return; if (style == "default") deleteCookie("GAPDocStyle"); else { /* ok, we set the cookie for path "/" */ var path = "/"; /* or better like this ??? var here = window.location.pathname.split("/"); for (var i=0; i+3 < here.length; i++) path = path+"/"+here[i]; */ document.cookie = "GAPDocStyle="+style+";Path="+path; /* split into names of style files */ var stlist = style.split(","); /* read style's css and js files */ for (var i=0; i < stlist.length; i++) { document.writeln(''); document.writeln(''); } } } /* this adds a "[Style]" link next to the MathJax switcher */ function addStyleLink() { var line = document.getElementById("mathjaxlink"); var el = document.createElement("a"); var oncl = document.createAttribute("href"); var back = window.location.protocol+"//" if (window.location.protocol == "http:" || window.location.protocol == "https:") { back = back+window.location.host; if (window.location.port != "") { back = back+":"+window.location.port; } } back = back+window.location.pathname; oncl.nodeValue = "chooser.html?BACK="+back; el.setAttributeNode(oncl); var cont = document.createTextNode(" [Style]"); el.appendChild(cont); line.appendChild(el); } var jscontentfuncs = new Array(); jscontentfuncs.push(addStyleLink); /* the default jscontent() only adds the [Style] link to the page */ function jscontent () { for (var i=0; i < jscontentfuncs.length; i++) jscontentfuncs[i](); } hapcryst-0.2.0/doc/chap4.txt0000644000175100017510000004202315160525022015260 0ustar runnerrunner 4 Resolutions of Crystallographic Groups 4.1 Fundamental Domains Let S be a crystallographic group. A Fundamental domain is a closed convex set containing a system of representatives for the Orbits of S in its natural action on euclidian space. There are two algorithms for calculating fundamental domains in HAPcryst. One uses the geometry and relies on having the standard rule for evaluating the scalar product (i.e. the gramian matrix is the identity). The other one is independent of the gramian matrix but does only work for Bieberbach groups, while the first ("geometric") algorithm works for arbitrary crystallographic groups given a point with trivial stabilizer. 4.1-1 FundamentalDomainStandardSpaceGroup FundamentalDomainStandardSpaceGroup( [v, ]G )  operation Returns: a PolymakeObject Let G be an AffineCrystGroupOnRight and v a vector. A fundamental domain containing v is calculated and returned as a PolymakeObject. The vector v is used as the starting point for a Dirichlet-Voronoi construction. If no v is given, the origin is used as starting point if it has trivial stabiliser. Otherwise an error is cast.  Example  gap> fd:=FundamentalDomainStandardSpaceGroup([1/2,0,1/5],SpaceGroup(3,9));  gap> Polymake(fd,"N_VERTICES"); 24 gap> fd:=FundamentalDomainStandardSpaceGroup(SpaceGroup(3,9));  gap> Polymake(fd,"N_VERTICES"); 8  4.1-2 FundamentalDomainBieberbachGroup FundamentalDomainBieberbachGroup( [v, ]G[, gram] )  operation Returns: a PolymakeObject Given a starting vector v and a Bieberbach group G in standard form, this method calculates the Dirichlet domain with respect to v. If gram is not supplied, the average gramian matrix is used (see GramianOfAverageScalarProductFromFiniteMatrixGroup (2.3-1)). It is not tested if gram is symmetric and positive definite. It is also not tested, if the product defined by gram is invariant under the point group of G. The behaviour of this function is influenced by the option ineqThreshold. The algorithm calculates approximations to a fundamental domain by iteratively adding inequalities. For an approximating polyhedron, every vertex is tested to find new inequalities. When all vertices have been considered or the number of new inequalities already found exceeds the value of ineqThreshold, a new approximating polyhedron in calculated. The default for ineqThreshold is 200. Roughly speaking, a large threshold means shifting work from polymake to GAP, a small one means more calls of (and work for) polymake. If the value of InfoHAPcryst (1.3-1) is 2 or more, for each approximation the number of vertices of the approximation, the number of vertices that have to be considered during the calculation, the number of facets, and new inequalities is shown. Note that the algorithm chooses vertices in random order and also writes inequalities for polymake in random order.  Example  gap> a0:=[[ 1, 0, 0, 0, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 0, 0 ],  >  [ 0, 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 0 ],  >  [ 0, 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, -1, -1, 0 ], >  [ -1/2, 0, 0, 1/6, 0, 0, 1 ]  >  ];; gap> a1:=[[ 0, -1, 0, 0, 0, 0, 0 ],[ 0, 0, -1, 0, 0, 0, 0 ], >  [ 1, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 0 ],  >  [ 0, 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 1, 0 ], >  [ 0, 0, 0, 0, 1/3, -1/3, 1 ]  >  ];; gap> trans:=List(Group((1,2,3,4,5,6)),g-> >  TranslationOnRightFromVector(Permuted([1,0,0,0,0,0],g)));; gap> S:=AffineCrystGroupOnRight(Concatenation(trans,[a0,a1]));  gap> SetInfoLevel(InfoHAPcryst,2); gap> FundamentalDomainBieberbachGroup(S:ineqThreshold:=10); #I v: 104/104 f:15 #I new: 201 #I v: 961/961 f:58 #I new: 20 #I v: 1143/805 f:69 #I new: 12 #I v: 1059/555 f:64 #I new: 15 #I v: 328/109 f:33 #I new: 12 #I v: 336/58 f:32 #I new: 0  gap> FundamentalDomainBieberbachGroup(S:ineqThreshold:=1000); #I v: 104/104 f:15 #I new: 149 #I v: 635/635 f:41 #I new: 115 #I v: 336/183 f:32 #I new: 0 #I out of inequalities   4.1-3 FundamentalDomainFromGeneralPointAndOrbitPartGeometric FundamentalDomainFromGeneralPointAndOrbitPartGeometric( v, orbit )  method Returns: a PolymakeObject This uses an alternative algorithm based on geometric considerations. It is not used in any of the high-level methods. Let v be a vector and orbit a sufficiently large part of the orbit of v under a crystallographic group with standard- orthogonal point group (satisfying A^t=A^-1). A geometric algorithm is then used to calculate the Dirichlet domain with respect to v. This also works for crystallographic groups which are not Bieberbach. The point v has to have trivial stabilizer. The intersection of the full orbit with the unit cube around v is sufficiently large.  Example  gap> G:=SpaceGroup(3,9);; gap> v:=[0,0,0]; [ 0, 0, 0 ] gap> orbit:=OrbitStabilizerInUnitCubeOnRight(G,v).orbit; [ [ 0, 0, 0 ], [ 0, 0, 1/2 ] ] gap> fd:=FundamentalDomainFromGeneralPointAndOrbitPartGeometric(v,orbit);  gap> Polymake(fd,"N_VERTICES"); 8  4.1-4 IsFundamentalDomainStandardSpaceGroup IsFundamentalDomainStandardSpaceGroup( poly, G )  method Returns: true or false This tests if a PolymakeObject poly is a fundamental domain for the affine crystallographic group G in standard form. The function tests the following: First, does the orbit of any vertex of poly have a point inside poly (if this is the case, false is returned). Second: Is every facet of poly the image of a different facet under a group element which does not fix poly. If this is satisfied, true is returned. 4.1-5 IsFundamentalDomainBieberbachGroup IsFundamentalDomainBieberbachGroup( poly, G )  method Returns: true, false or fail This tests if a PolymakeObject poly is a fundamental domain for the affine crystallographic group G in standard form and if this group is torsion free (ie a Bieberbach group) It returns true if G is torsion free and poly is a fundamental domain for G. If poly is not a fundamental domain, false is returned regardless of the structure of G. And if G is not torsion free, the method returns fail. If G is polycyclic, torsion freeness is tested using a representation as pcp group. Otherwise the stabilisers of the faces of the fundamental domain poly are calculated (G is torsion free if and only if it all these stabilisers are trivial). 4.2 Face Lattice and Resolution For Bieberbach groups (torsion free crystallographic groups), the following functions calcualte free resolutions. This calculation is done by finding a fundamental domain for the group. For a description of the HapResolution datatype, see the Hap data types documentation or the experimental datatypes documentation A 4.2-1 ResolutionBieberbachGroup ResolutionBieberbachGroup( G[, v] )  method Returns: a HAPresolution Let G be a Bieberbach group given as an AffineCrystGroupOnRight and v a vector. Then a Dirichlet domain with respect to v is calculated using FundamentalDomainBieberbachGroup (4.1-2). From this domain, a resolution is calculated using FaceLatticeAndBoundaryBieberbachGroup (4.2-2) and ResolutionFromFLandBoundary (4.2-3). If v is not given, the origin is used.  Example  gap> R:=ResolutionBieberbachGroup(SpaceGroup(3,9)); Resolution of length 3 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 2, 2, 2, 2 ) . No contracting homotopy available.  gap> List([0..3],Dimension(R)); [ 1, 3, 3, 1 ] gap> R:=ResolutionBieberbachGroup(SpaceGroup(3,9),[1/2,0,0]); Resolution of length 3 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 2, 2, 2, 2 ) . No contracting homotopy available.  gap> List([0..3],Dimension(R)); [ 6, 12, 7, 1 ]  4.2-2 FaceLatticeAndBoundaryBieberbachGroup FaceLatticeAndBoundaryBieberbachGroup( poly, group )  method Returns: Record with entries .hasse and .elts representing a part of the hasse diagram and a lookup table of group elements Let group be a torsion free AffineCrystGroupOnRight (that is, a Bieberbach group). Given a PolymakeObject poly representing a fundamental domain for group, this method uses polymaking to calculate the face lattice of poly. From the set of faces, a system of representatives for group- orbits is chosen. For each representative, the boundary is then calculated. The list .elts contains elements of group (in fact, it is even a set). The structure of the returned list .hasse is as follows:  The i-th entry contains a system of representatives for the i-1 dimensional faces of poly.  Each face is represented by a pair of lists [vertices,boundary]. The list of integers vertices represents the vertices of poly which are contained in this face. The enumeration is chosen such that an i in the list represents the i-th entry of the list Polymake(poly,"VERTICES");  The list boundary represents the boundary of the respective face. It is a list of pairs of integers [j,g]. The first entry lies between -n and n, where n is the number of faces of dimension i-1. This entry represents a face of dimension i-1 (or its additive inverse as a module generator). The second entry g is the position of the matrix in .elts. This representation is compatible with the representation of free Z G modules in Hap and this method essentially calculates a free resolution of group. If the value of InfoHAPcryst (1.3-1) is 2 or more, additional information about the number of faces in every codimension, the number of orbits of the group on the free module generated by those faces, and the time it took to calculate the orbit decomposition is output.  Example  gap> SetInfoLevel(InfoHAPcryst,2); gap> G:=SpaceGroup(3,165); SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) gap> fd:=FundamentalDomainBieberbachGroup(G);  gap> fl:=FaceLatticeAndBoundaryBieberbachGroup(fd,G);; #I 1(4/8): 0:00:00.004 #I 2(5/18): 0:00:00.000 #I 3(2/12): 0:00:00.000 #I Face lattice done ( 0:00:00.004). Calculating boundary #I done ( 0:00:00.004) Reformating... gap> RecNames(fl); [ "hasse", "elts", "groupring" ] gap> fl.groupring;   4.2-3 ResolutionFromFLandBoundary ResolutionFromFLandBoundary( fl, group )  method Returns: Free resolution If fl is the record output by FaceLatticeAndBoundaryBieberbachGroup (4.2-2) and group is the corresponding group, this function returns a HapResolution. Of course, fl has to be generated from a fundamental domain for group  Example  gap> G:=SpaceGroup(3,165); SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) gap> fd:=FundamentalDomainBieberbachGroup(G);  gap> fl:=FaceLatticeAndBoundaryBieberbachGroup(fd,G);; gap> ResolutionFromFLandBoundary(fl,G); Resolution of length 3 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) . No contracting homotopy available.  gap> ResolutionFromFLandBoundary(fl,G); Resolution of length 3 in characteristic 0 for SpaceGroupOnRightBBNWZ( 3, 6, 1, 1, 4 ) . No contracting homotopy available.  gap> List([0..4],Dimension(last)); [ 2, 5, 4, 1, 0 ]  hapcryst-0.2.0/doc/spacegroups.xml0000644000175100017510000002304115160525022016574 0ustar runnerrunnerWe introduce a way to calculate a sufficient part of an orbit and the stabilizer of a point.
Orbit Stabilizer for Crystallographic Groups A record containing .stabilizer: the stabilizer of x. .orbit set of vectors from [0,1)^n which represents the orbit. Let x be a rational vector from [0,1)^n and group a space group in standard form. The function then calculates the part of the orbit which lies inside the cube [0,1)^n and the stabilizer of x. Observe that every element of the full orbit differs from a point in the returned orbit only by a pure translation. Note that the restriction to points from [0,1)^n makes sense if orbits should be compared and the vector passed to OrbitStabilizerInUnitCubeOnRight should be an element of the returned orbit (part). S:=SpaceGroup(3,5);; gap> OrbitStabilizerInUnitCubeOnRight(S,[1/2,0,9/11]); rec( orbit := [ [ 0, 1/2, 2/11 ], [ 1/2, 0, 9/11 ] ], stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ]) ) gap> OrbitStabilizerInUnitCubeOnRight(S,[0,0,0]); rec( orbit := [ [ 0, 0, 0 ] ], stabilizer := ) ]]> If you are interested in other parts of the orbit, you can use for the base point and the functions , and for the resulting orbit
Suppose we want to calculate the part of the orbit of [4/3,5/3,7/3] in the cube of sidelength 1 around this point: S:=SpaceGroup(3,5);; gap> p:=[4/3,5/3,7/3];; gap> o:=OrbitStabilizerInUnitCubeOnRight(S,VectorModOne(p)).orbit; [ [ 1/3, 2/3, 1/3 ], [ 1/3, 2/3, 2/3 ] ] gap> box:=p+[[-1,1],[-1,1],[-1,1]]; [ [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ] ] gap> o2:=Concatenation(List(o,i->i+TranslationsToBox(i,box)));; gap> # This is what we looked for. But it is somewhat large: gap> Size(o2); 54 ]]> A record containing .stabilizer: the stabilizer of set. .orbit set of sets of vectors from [0,1)^n which represents the orbit. Calculates orbit and stabilizer of a set of vectors. Just as , it needs input from [0,1)^n. The returned orbit part .orbit is a set of sets such that every element of .orbit has a non-trivial intersection with the cube [0,1)^n. In general, these sets will not lie inside [0,1)^n completely. S:=SpaceGroup(3,5);; gap> OrbitStabilizerInUnitCubeOnRightOnSets(S,[[0,0,0],[0,1/2,0]]); rec( orbit := [ [ [ -1/2, 0, 0 ], [ 0, 0, 0 ] ], [ [ 0, 0, 0 ], [ 0, 1/2, 0 ] ], [ [ 1/2, 0, 0 ], [ 1, 0, 0 ] ] ], stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ]) ) ]]> Set of subsets of allvertices. If allvertices is a set of vectors and vertexset is a subset thereof, then returns that part of the orbit of vertexset which consists entirely of subsets of allvertices. Note that,unlike the other OrbitStabilizer algorithms, this does not require the input to lie in some particular part of the space. S:=SpaceGroup(3,5);; gap> OrbitPartInVertexSetsStandardSpaceGroup(S,[[0,1,5],[1,2,0]], > Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]])); [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 2, 6 ], [ 2, 3, 1 ] ] ] gap> OrbitPartInVertexSetsStandardSpaceGroup(S, [[1,2,0]], > Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]])); [ [ [ 0, 1, 5 ] ], [ [ 1, 1, 0 ] ], [ [ 1, 2, 0 ] ], [ [ 1, 2, 6 ] ], [ [ 2, 3, 1 ] ] ] ]]> Set of subsets of faceset. This calculates the orbit of a space group on sets restricted to a set of faces.
If faceset is a set of sets of vectors and vertexset is an element of faceset, then returns that part of the orbit of vertexset which consists entirely of elements of faceset.
Note that,unlike the other OrbitStabilizer algorithms, this does not require the input to lie in some particular part of the space.
A set of face-matrix pairs . This is a slight variation of that also returns a representative for every orbit element. S:=SpaceGroup(3,5);; gap> OrbitPartInVertexSetsStandardSpaceGroup(S,[[0,1,5],[1,2,0]], > Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]])); [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 2, 6 ], [ 2, 3, 1 ] ] ] gap> OrbitPartInFacesStandardSpaceGroup(S,[[0,1,5],[1,2,0]], > Set( [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [[1/17,6,1/2],[1,2,7]]])); [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ] ] gap> OrbitPartAndRepresentativesInFacesStandardSpaceGroup(S,[[0,1,5],[1,2,0]], > Set( [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [[1/17,6,1/2],[1,2,7]]])); [ [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ] ] ]]> finite group of affine matrices (OnRight) Given a set set of vectors and a space group group in standard form, this method calculates the stabilizer of that set in the full crystallographic group.
G:=SpaceGroup(3,12);; gap> v:=[ 0, 0,0 ];; gap> s:=StabilizerOnSetsStandardSpaceGroup(G,[v]); gap> s2:=OrbitStabilizerInUnitCubeOnRight(G,v).stabilizer; gap> s2=s; true ]]> Affine matrix. Returns an element of the space group S which takes the set set to the set imageset. The group must be in standard form and act on the right. S:=SpaceGroup(3,5);; gap> RepresentativeActionOnRightOnSets(G, [[0,0,0],[0,1/2,0]], > [ [ 0, 1/2, 0 ], [ 0, 1, 0 ] ]); [ [ 0, -1, 0, 0 ], [ -1, 0, 0, 0 ], [ 0, 0, -1, 0 ], [ 0, 1, 0, 1 ] ] ]]> Getting other orbit parts HAPcryst does not calculate the full orbit but only the part of it having coefficients between -1/2 and 1/2. The other parts of the orbit can be calculated using the following functions. Set of vectors Takes each vector in orbitpart to the cube unit cube centered in point. ShiftedOrbitPart([0,0,0],[[1/2,1/2,1/3],-[1/2,1/2,1/2],[19,3,1]]); [ [ 1/2, 1/2, 1/3 ], [ 1/2, 1/2, 1/2 ], [ 0, 0, 0 ] ] gap> ShiftedOrbitPart([1,1,1],[[1/2,1/2,1/2],-[1/2,1/2,1/2]]); [ [ 3/2, 3/2, 3/2 ] ] ]]> List of integer vectors This method returns the list of all integer vectors which translate point into the box center+[-1/2,1/2]^n TranslationsToOneCubeAroundCenter([1/2,1/2,1/3],[0,0,0]); [ [ 0, 0, 0 ], [ 0, -1, 0 ], [ -1, 0, 0 ], [ -1, -1, 0 ] ] gap> TranslationsToOneCubeAroundCenter([1,0,1],[0,0,0]); [ [ -1, 0, -1 ] ] ]]> List of integer vectors or the empty list Given a vector v and a list of pairs, this function returns the translation vectors (integer vectors) which take v into the box box. The box box has to be given as a list of pairs. TranslationsToBox([0,0],[[1/2,2/3],[1/2,2/3]]); [ ] gap> TranslationsToBox([0,0],[[-3/2,1/2],[1,4/3]]); [ [ -1, 1 ], [ 0, 1 ] ] gap> TranslationsToBox([0,0],[[-3/2,1/2],[2,1]]); Error, Box must not be empty ]]>
hapcryst-0.2.0/doc/resolutionAccess_GroupRing.xml0000644000175100017510000001413615160525022021567 0ustar runnerrunner
The HapLargeGroupResolutionRep Representation The large group representation has one additional component called groupring. Elements of the modules in a resolution are represented by lists of group ring elements. The length of the list corresponds to the dimension of the free module.

All methods for the generic representation do also work for the large group representation. Some of them are wrappers for special methods which do only work for this representation. The following list only contains the methods which are not already present in the generic representation.

Note that the input or the output of these functions does not comply with the standard representation. group ring This returns the group ring of resolution. Note that by the way that group rings are handled in &GAP;, this is not equal to GroupRing(R,GroupOfResolution(resolution)) where R is the ring of the resolution. group element Returns the product of x and y. The NC version does not check whether x and y are actually elements of the group of resolution. boolean Returns true if letter has the form of a letter (a module element with exactly one non-zero entry which has exactly one non-zero coefficient) a module of resolution in the HapLargeGroupResolution representation. Note that it is not tested if letter actually is a letter in any term of resolution boolean Returns true if word has the form of a word of a module of resolution in the HapLargeGroupResolution representation. Note that it is not tested if word actually is a word in any term of resolution. boolean Returns true if and only if letter is a letter (a word of length 1) of the termth module of resolution in the hapLargeGroupResolution representation. I.e. it tests if letter is a module element with exactly one non-zero entry which has exactly one non-zero coefficient. boolean Tests if word is an element of the termth module of resoultion. free ZG letter in large group representation Multiplies the letter letter with the group element g and returns the result. The NC version does not check whether g is an element of the group of resolution and letter can be a letter. free ZG word in large group representation Multiplies the word word with the group element g and returns the result. The NC version does not check whether g is an element of the group of resolution and word can be a word. list of letters/words in large group representation Returns a set of generators for the termth module of resolution. The returned value is a list of vectors of group ring elements. free ZG word in the large group representation Returns the boundary of the nth generator of the termth module of resolution as a word in the n-1st module (in large group representation). The NC version does not check whether there is a termth module and if it has at least n generators. free ZG word in large group representation Calculates the boundary of the letter letter of the termth module of resolution in large group representation. The NC version does not check whether letter actually is a letter in the termth module. free ZG word in large group representation Calculates the boundary of the element word of the termth module of resolution in large group representation. The NC version does not check whether word actually is a word in the termth module.

hapcryst-0.2.0/doc/toggless.css0000644000175100017510000000167215160525022016066 0ustar runnerrunner/* toggless.css Frank LĂ¼beck */ /* Using javascript we change all div.ContSect to div.ContSectOpen or div.ContSectClosed. This way the config for div.ContSect in manual.css is no longer relevant. Here we add the CSS for the new elements. */ /* This layout is based on an idea by Burkhard Höfling. */ div.ContSectClosed { text-align: left; margin-left: 1em; } div.ContSectOpen { text-align: left; margin-left: 1em; } div.ContSectOpen div.ContSSBlock { display: block; text-align: left; margin-left: 1em; } div.ContSectOpen div.ContSSBlock a { display: block; width: 100%; margin-left: 1em; } span.tocline a:hover { display: inline; background: #eeeeee; } span.ContSS a:hover { display: inline; background: #eeeeee; } span.toctoggle { font-size: 80%; display: inline-block; width: 1.2em; } span.toctoggle:hover { background-color: #aaaaaa; } hapcryst-0.2.0/doc/intro.xml0000644000175100017510000001345315160525022015402 0ustar runnerrunner
Abstract and Notation HAPcryst is an extension for "Homological Algebra Programming" (HAP, ) by Graham Ellis. It uses geometric methods to calculate resolutions for crystallographic groups. In this manual, we will use the terms "space group" and "crystallographic group" synonymous. As usual in &GAP;, group elements are supposed to act from the right. To emphasize this fact, some functions have names ending in "OnRight" (namely those, which rely on the action from the right). This is also meant to make work with HAPcryst and cryst easier.

The functions called "somethingStandardSpaceGroup" are supposed to work for standard crystallographic groups on left and right some time in the future. Currently only the versions acting on right are implemented. As in cryst , space groups are represented as affine linear groups. For the computations in HAPcryst, crystallographic groups have to be in "standard form". That is, the translation basis has to be the standard basis of the space. This implies that the linear part of a group element need not be orthogonal with respect to the usual scalar product. The natural action of crystallographic groups action of crystallographic groups There is some confusion about the way crystallographic groups are written. This concerns the question if we act on left or on right and if vectors are of the form [1,...] or [...,1].

As mentioned, HAPcryst handles affine crystallographic groups on right (and maybe later also on left) acting on vectors of the form [...,1].

BUT: The functions in HAPcryst do not take augmented vectors as input (no leading or ending ones). The handling of vectors is done internally. So in HAPcryst, a crystallographic group is a group of n\times n matrices which acts on a vector space of dimension n-1 whose elements are vectors of length n-1 (not n). Example: G:=SpaceGroup(3,4); #This group acts on 3-Space SpaceGroupOnRightBBNWZ( 3, 2, 1, 1, 2 ) gap> Display(Representative(G)); [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] gap> OrbitStabilizerInUnitCubeOnRight(G,[1/2,0,0]); rec( orbit := [ [ 1/2, 0, 0 ], [ 1/2, 1/2, 0 ] ], stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ]) ) ]]>
Requirementsinstallation The following &GAP; packages are required polymaking which in turn depends on the computational geometry software polymake. HAP Cryst The following &GAP; packages are not required but highly recommended: carat CrystCat GAPDoc is needed to display the online manual Recommendation concerning polymake polymake Calculating resolutions of Bieberbach groups involves convex hull computations. polymake by default uses cdd to compute convex hulls. Experiments suggest that lrs is the more suitable algorithm for the computations done in HAPcryst than the default cdd. You can change the behaviour of by editing the file "yourhomedirectory/.polymake/prefer.pl". It should contain a section like this (just make sure lrs is before cdd, the position of beneath_beyond does not matter): ######################################### application polytope; prefer "*.convex_hull lrs, beneath_beyond, cdd";
Global Variables HAPcryst itself does only have one global variable, namely . The location of files generated for interaction with polymake are determined by the value of which is a global variable of polymaking. At a level of 1, only the most important messages are printed. At level 2, additional information is displayed, and level 3 is even more verbose. At level 0, HAPcryst remains silent.
hapcryst-0.2.0/doc/misc.xml0000644000175100017510000001612215160525022015176 0ustar runnerrunnerThis chapter contains a few very basic functions which are needed for space group calculations and were missing in standard &GAP;.
Matrices and Vectors sign of the rational number x (Standard &GAP; currently only has SignInt). Rational vector of the same length with enties in [0,1) For a rational vector v, this returns the vector with all entries taken "mod 1". SignRat((-4)/(-2)); 1 gap> SignRat(9/(-2)); -1 gap> VectorModOne([1/10,100/9,5/6,6/5]); [ 1/10, 1/9, 5/6, 1/5 ] ]]> true if matrix is a square matrix and false otherwise. Number of lines in the matrix matrix if it is square and fail otherwise m:=[[1,2,3],[4,5,6],[9,6,12]]; [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 9, 6, 12 ] ] gap> IsSquareMat(m); true gap> DimensionSquareMat(m); 3 gap> DimensionSquareMat([[1,2],[1,2,3]]); fail ]]> Affine mappings of n dimensional space are often written as a pair (A,v) where A is a linear mapping and v is a vector. &GAP; represents affine mappings by n+1 times n+1 matrices M which satisfy M_{{n+1,n+1}}=1 and M_{{i,n+1}}=0 for all 1\leq i \leq n.

An affine matrix acts on an n dimensional space which is written as a space of n+1 tuples with n+1st entry 1. Here we give two functions to handle these affine matrices.
Affine Matrices OnRight the linear part of the affine matrix mat. That is, everything except for the last row and column. affine matrix with same dimensions as mat A basis change transform of an n dimensional space induces a transformation on affine mappings on this space. If mat is a affine matrix (in particular, it is (n+1)\times (n+1)), this method returns the image of mat under the basis transformation induced by transform. c:=[[0,1],[1,0]]; [ [ 0, 1 ], [ 1, 0 ] ] gap> m:=[[1/2,0,0],[0,2/3,0],[1,0,1]]; [ [ 1/2, 0, 0 ], [ 0, 2/3, 0 ], [ 1, 0, 1 ] ] gap> BasisChangeAffineMatOnRight(c,m); [ [ 2/3, 0, 0 ], [ 0, 1/2, 0 ], [ 0, 1, 1 ] ] ]]> Affine matrix Given a vector v with n entries, this method returns a (n+1)\times (n+1) matrix which corresponds to the affine translation defined by v. m:=TranslationOnRightFromVector([1,2,3]);; gap> Display(m); [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 1, 2, 3, 1 ] ] gap> LinearPartOfAffineMatOnRight(m); [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ] gap> BasisChangeAffineMatOnRight([[3,2,1],[0,1,0],[0,0,1]],m); [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 3, 4, 4, 1 ] ] ]]>
Geometry Symmetric positive definite matrix For a finite matrix group G, the gramian matrix of the average scalar product is returned. This is the sum over all gg^t with g\in G (actually it is enough to take a generating set). The group G is orthogonal with respect to the scalar product induced by the returned matrix. Inequalities Inequalities are represented in the same way they are represented in polymaking. The vector (v_0,\ldots,v_n) represents the inequality 0\leq v_0+v_1 x_1+\ldots + v_n x_n. vector of length Length(v1)+1 Calculates the inequality defining the half-space containing v1 such that v1-v2 is perpendicular on the bounding hyperplane. And (v1-v2)/2 is contained in the bounding hyperplane.
If the matrix gram is given, it is used as the gramian matrix. Otherwiese, the standard scalar product is used. It is not checked if gram is positive definite or symmetric.
-1 (below) 0 (in) or 1 (above). Let v be a vector of length n and ineq an inequality represented by a vector of length n+1. Then WhichSideOfHyperplane(v, ineq) returns 1 if v is a solution of the inequality but not the equation given by ineq, it returns 0 if v is a solution to the equation and -1 if it is not a solution of the inequality ineq.

The NC version does not test the input for correctness. BisectorInequalityFromPointPair([0,0],[1,0]); [ 1, -2, 0 ] gap> ineq:=BisectorInequalityFromPointPair([0,0],[1,0],[[5,4],[4,5]]); [ 5, -10, -8 ] gap> ineq{[2,3]}*[1/2,0]; -5 gap> WhichSideOfHyperplane([0,0],ineq); 1 gap> WhichSideOfHyperplane([1/2,0],ineq); 0 ]]> one of "VERTEX", "FACET", "OUTSIDE", "INSIDE" Let poly be a PolymakeObject and point a vector. If point is a vertex of poly, the string "VERTEX" is returned. If point lies inside poly, "INSIDE" is returned and if it lies in a facet, "FACET" is returned and if point does not lie inside poly, the function returns "OUTSIDE".

Space Groups list of matrices Given an AffineCrystGroupOnLeftOrRight group, this returns a list of representatives of the point group of group. That is, a system of representatives for the factor group modulo translations. This is an attribute of AffineCrystGroupOnLeftOrRight
hapcryst-0.2.0/doc/manual.pdf0000644000175100017510000066406115160525022015504 0ustar runnerrunner%PDF-1.5 %ĐÔÅØ 110 0 obj << /Length 334 /Filter /FlateDecode >> stream xÚ…’ÁjĂ0 †ïy “C4ɶ{§uĐu £„]Æ!MÓBÛ·ƒíígÇ¥]e#ËøûơK6^ ˜ex#>ÖÙƯ“¶B;°¤¤¨—‚œF+ 1¨E½ùóä­ơ?‡cñY¿Œ€ÔPÙ"P:-Mˆl«LR2F.mºïc·;¬‡]J—…ä|đ)•›Ífè}³_­ÛXD +EITIµ÷Ù|øÚ’Æ+#̉®b Hur₫^Q̃ùKm xæ Á¡y¥˜E© ¬;áR'èµñí*m%JsiPÚŒƒ+5H c 2ÀR&>pÑr›ĐùĐ-:†8ÙĐ*‹th‚YưG禀µKÔtÛ¬7÷ñ^†€"-f-|/®æ³øüƠ©PƯ° £’+Â64_””?ôQÚa›Äo|ªiưƠ`•Ó endstream endobj 120 0 obj << /Length 540 /Filter /FlateDecode >> stream xÚSMs›0¼ûWè„>„zK]ÇưH<™„ê0–1cŒơøßWX²ÏĐN û¤·+ôvA ,gŸ³Y|ÏR  ƒlˆH!–¡Ä ȶàWđơî©Đ§̃„¿³ï¶Œ D̉(ƒ(•VîÜJÆ̣úñ}’œ@p26G åP0 "ËJ9sœyÛtUîßô%”œđ‘@D$\¸Ö5a8ŒCAH8ô˜ë¡ç5å|«tÈXG1€9”T€ÛÛ0\¶¯zÛ/̉ Ë‹C^*W¸El«̃èj FmƯæĐŒ²ghö`”~ơBíÎq¯{ËƠOT£t^»âiØÔUáđCU¨¦÷íB̀¥ûªmœñº₫̀:7—ă׈¡Ü8|j}¾f4uÏÂ%Èk7•j eɆÅ(xQÊ Í}³k„H­œ‰xçF‰µ›_,~ø6_¬^fQ ‘d—¾V»,@ÜĂXt nÏ)¹=·@íéúOq|<†°lØê2.lhjµ3q9®w5Ü›×úÿáĂ,B‚HP(‰̉]qhÚĐÎăX«m©^UcúÄÚÄâ›Ù¡Gn«ïªÜoơC×µÚEÈ–›Ó5®•Ÿø|¸Â¥Îăàªơ=f?¾LØAh )»9ø\ ¹NpMyJ  äĂöoăS*̣<ɪ „đ”Ư˜ty/²Ù_ñ  endstream endobj 153 0 obj << /Length 1142 /Filter /FlateDecode >> stream xÚíZ]“Ú6}ß_áGó`Eß–t7é$m†eú²Íƒ165¦íö×GÆ`³›Z†aBÀ°́{ÏÑ9÷ʆ̃ƒ̃춃ñƯ»{*B†̀ÎîÔ´u GP ¡ µ€Ö¡0è÷'›è̀¤éG̃P)Íf—Ć’Đ¢i9ư¿¹+ˆXÇ;à7̉m£L¯&ÂÑsÊn¬n@²@2‹#qÀñ!N'*.'ß=„¯²HMbƯÙÂGơNî gÓ/d¼‡S/0¶DYåAØÁ5‘™¢u™ưéi„ F”û¼£oØ@U;¹Æg•gQqåơpJâêif‚ Ù;?Ó9°“sôç=̀ü?!ĉ.á«£ú{2˼˜ßráÙÈ9y…NW:Ï;@Ñ­û}[HÅyîu@ôq­¦Ơ$|È̉íºK)‡ÄO0_S¾…÷ïïÇ‹4‹̣åª×t^‰l6‰vûî^ĐGC ¸´bP₫¥~Q pÚ<æjÅÑ:+÷Bê?¯u‡ê3}»6¥RÉI]߈SuQ&eF3¬yZ}fÏ›\ÅqºÈÔzMÏ›Đ ók΅K:!ƒÈǴ¥n¥̀Ô‰‹÷Ûd¦îÚ6gïÓ•’‘̃ú–„eg–GÔ©°½ï!æïưô“ÊóÈî́;•ƒ;P2Ä·x ­é·C3 Å©ÔDI¹ư Ö “c£ 6Îư¶r"°đÇK½÷5£+ÙëLo ‘±Œ<)˜I·fob?äǺ˜ˆfX’€ ;ø•­Ự=bíÄđM&XØ ¬  Å] |Å'•-ô®̣ẹ́¸œpˆJ€%³ÇŸBïX¹đ«ÁŸ+Æë¥¨̉ ²AKÀñûÓ©̃l¢dÑûÏ*‰ÖÛØdØ₫t¬*î"CĂL.("ƒÖ""H µæä„6‡úUÔ‡ÉL¯µyKª²»̀d•=/ÓY—”Éë^.iKœ¥Er£,¨‰ nàĐÀF¡ÿwQ¨è́@ËÎÿÑ:yÉ6?ü¸×‹|nư8h»¼V€ó¸ÖÓÈVû–üûæó%o63ËW¼ÙÂÙö,âèŹÙy~qwëF̀èÿÉ£í1üiƯn…obƯĂöe~ñ,GñÂ^ ?¤«4O×Q§ûŸ!ƒÂ'đ‚=t1èV́û¢Œđ«ØnØgb¯¢~nÁ¾÷*Wv©OÀnK}‚̣«Ô /ËGa'́\ï–¢t²¿ëzx$™́î;,‚[fÓ ́‘µSƠ¿ß?C½î8YFʼnMHImɹ:æ—ñƯ7–Ô²H endstream endobj 162 0 obj << /Length 2537 /Filter /FlateDecode >> stream xÚ½ZƯsÛ6÷_¡q_è ÁÁtz3I.qÓ‡¤—¸Ó™óù–`ISTIª®û×ß. H‰v¢ÔÓ@p±Ø]́₫v—2Ÿ,'|ryÆưøúếÅ»8›HÎ’DêÉƠƯ$M˜Vz’hÁ”̀'W‹Éuôfe¶­­/fRóH\Ü\ưtÆŸ„¿z9é?~ºôLc–f©@¦|2‹s– Eü̃—m}!²¨Źæíº*‰£—Éí1Sq"ư^'¿W°¯`r=œóèƠmÓÖf̃’è¦\ĐäCƠ‘ƒs5œå<Bƒ YLç₫øêç9X@ñè¡iqß‹w÷ÉAAÅ3ØåÈ× ĐJG̉h/„₫lmÙà±n鮪ir₫cµ©j¹›WdôªXÚÛÚĐëŸëjY›Íf].Ïiå\sa(±L“±2€Èc‚JÉb¸YO4%–×FƠ:œa£·E1°,Ư€D‚Ư>ĐxY›•ÙĐv¬†›&3¥$ËÓl2 xz€ûQZE»Æ¢Ù´Œ–¶Úض^Ïé̀WƠ¿k+ZkÍw…i-=Ö¶©̃ª§#û"a Wf͸]O8¢®v[j–€'¾/‰´]­ưî)w¦@ë¤ytođœ¤}XܯÁ3™$(8N4́·´á²ihz̃lÍÜ¿w‡Ó:y# xHÛ<”à6àB›j‡B+F¯púδg]ù…Ê2ƳîÊ/ñ ÅxÜs díd ‹‹„øÍÀ¶°[¶(jT“ë¨Ùm·Uc´Œæ^»8„É]]mˆ́Kơz¹jA/™ëèê"ă‘ßc7Û•iÖy2ºÜyw!8rDAÁ. ø‹±+ç̃ pÇÊ\Hư¶ó?O@́Ùù# f$¨HX®̉á½™đ1ÚĐÜå {×̉̀¡ NœgÑ”‚gí:̀Ö~§óDœÜíÚ]mÁ 5Ï¢7»º†8G¯¦c¬#‡‹1ËEuăÍ'Rñ"Âs”p=Ñ &3á$gßl d†àb D̀cÂ;|9 rBá<ùj7‹¡̃y7ĂøỊ̈(À<讥ơ:ár”SÈkÛøñîBj€.K¯~á¬fMM]ªB+¼C(×!̉H)qà"îNdÍ«ÍvG•NC+ă¦Ë¡lHÅ×Ǽ†rL÷ ˆX%YÙóMyˆÄ Tvqonm'Ï{(›stD•B Ö7₫dT—Œ¡RÆur`ŒÚ”Ma<è¦<º8@ç%‘Ÿ;Å×–FBdx±—e°ùîq=nĂ*º̣Ú6ÅïíâQ.h·¦n‡̀ ½Øça>À-Ÿ èJk}}[V~Éi£t S-«̉Ơ đ́ĐßÍÀ%·6ÈÎ:“PZÀ´,4¾ØÖ®tgäX¯ –kêu™ƒ¯È®^?©b¿ G—đ'̃eMíMăHƠ«Kê,Đë†ÅưЇQJx  œZụ̂ ¡¢À0*ïvT·»2æ¶Úµ¡ñE‡CvóàéăûP@r»¯×-4¡đñƠ;rnëPĂtỦï;Û„¾å¨bñf¹·É¼½¼Ư('7 ßî·HÅë¼­êÆSÔvx³`œ’G@ÓÔ[h̉´+®Å”1v3,ú­.ûÈrWËDW \«©e¦r'ª…ö?×jh:—Xe°®]LÇP2Ñ,ÏƠ)•‘â]ͽĂÖŸsøJ¹Œê¥å I%»»‚%,Fé¾Pvópë™aOTû“¨X¤ư$́ƠA®A-\6LÙ}9rƒ'nJ–₫}açÏå ׂi4ĐyÈâ%€²ûû~̀¬ ¶̀;³±5‹uç ă®Ñ?ơRiv`˜×˜s£_°®^b“y„ÊƠ Ó€ÇGÊƒĂ‰SÜ&ßÀ‹x Ă¤ƯøđdvËM((̣¸wI>¯Áé¤Ûî<×ÄxÆ…5 ºlxp¸c¯-‰đ;YB¤ézé "SrrâOÎC`º,P'“€r¥ß¸jHNPU&X¦;¶Ÿ«đr´O‰9KâøÛ‹tÂHôÁ*åÜÄi ïuÅ2KÜ×”×€æ$qv\{ló:AÊ@ KöІø0Æ'g‰̉|†º¦,Í»~kcđ;ƒ¸‡Đ¤B±aî]Ăhh蹑# …-R̃Ѹ€¾>e(%Æè‰ª̣1Eª AƠxil×#xE(7 Thú‚Çàïå²k|RC¥Wù˜đ€__”=ÏE_v€¼vÔhØ#ÇO^ë×Bü¼ưÓ`»ổ‘›ù-2¸KñwXx!œ”R<ÍÊ`Ï¢×>Ûa? Ÿ.GŒœÇ Åëqoă¥Ù₫ËиoPB÷¨ˆÖPY\¾ü>M\̀ í¬B¿SÓ}æû G̣Ơ8ơ8‡S‚œ!$à¨fÈ ùØĂ&ù¥BÅ=p‡p§[ñø"2Ít’œÀâQ3‹,gBû`ÿ1ç#ªKŸư^¿₫đëƯçv²Æ”FéGq0J\)u NVàØ©øü‡œQ¤)ù7;ă¿×Ͷ0hÄOÎüWhÉÿ°¸z‰æ"×|;Ù4ÇÖMKôóx4 2V¡ôuApü!mê'ÜMâÜOp…(o¦OxÑÉBë‰}KOHŒ,ƒvˆÉ,íí)6®êWhx²xÇ*(…âäy4Œä?ùˆ†ª~¥†'‹w¬¡„º6%$ø4ư’‚Ư ¯`WóTµ„’,SúÂ;‘BI/¿ï>Ö·ëöskńÖÅú/[¿/)×í›Ư­Å_“p~äá—ÓkñBNù”ß<l«csCù‘eÏ‚ÖÄûTmçûTZ¡™hụ́‡{†f<Œ]DÓơv ]ó©> stream xÚåZ]sÛº}ׯÀc’X|w Hpqö́Á©…N%¼ĐJ‹$´18äÅ ´ÆE¡ƒ0I …VNÛ‘đÊ£µđ& ̣"à>J"à>M: ØKN caV‘00¨đ͵V0¦Q›8²Ä]ă?÷”°äÀ’·F8îÚ¡¼p°—’.RèIG-¼DFtïÇ Ï(ê˜dº ˆ‹LH®x专Ƥ0Ä,X®×^D¸†‡ÑFj¬B‘Yƒ@³gR@ £ ®Ùj–­£4̉ Ă:fT9x‹[¸{ë·ÁM¾¾ÄlkP£qWV?NiVÂG8‰P0A8̣fÄƯ;kp~: Ï4(§™̣ˆp£́x;ˆKđVƒDÏæ5áẸ́™ÈaåÛ™GíG…â9°î8Đ HTœ²NÜ Aƒ6̀.ŒiĂôz> Äw`\ĂkÅÇ‘¶JDnØ“È 5‰]Fô£U|†ég¡€×è3TÑ‘`­Ô¡`̀ø\j¤…=…dĐ]@£É± ¡‹äØT“¼Ăí`?sqÍÅ$_æ«óÇ;¬ËI5]̀¥îêæ”‹O\¬Û}Û=|TVåÓóŒcsúO@•[ư 2ÚEö–‹’‹f§^}á*m‰Z÷ucv»yÎÅ,£ü”áÏnû÷{>½Ê8ƹư,ăèè}ăϲ­*GàÑọ-ePyÀoê üëvœ¶nƯ2yßÛPªLäê (Ú£Æ/¹˜æ>ËÛ}₫,ô?g3osÓK.¾Ö6ú0îL™ưÜjp æGŸI»ḳËö¨kyü¼®sû½™=ôβû‹6{U¦äj‡ÂEI‹ÔU[ – —ƯªÚCe!ÔGÿή®n_³˜½,÷óiº´½ÛÆ₫¯#û̉&nsú|ûv.Ư¦’m¹l'Ùeæ}+âû̃öå̉u¶5Ëï&ê#¢ÿ¿àïF¶KỊ̈íÛœ5̃÷̀ØÍ÷OÛă{ÜÎF½`h˜=CûU;™UÉ́@ ₫¹àîB/—åüóô»<\8[Ê6g^le°ŸÄÓ®ˆ¾Ï²){†̣h¯zØZ¶'ë}Âẹ̀²Ă_£ëœ>>èh>î zƠ¦â2·ß;̉îåðL÷hơlÏÓm̉1X·¥xyĘzƯ¾6Í^\g:î ̃5ư cg¿κ†Ä0Z̃>°_¶ÉØZ.;.̀wªưhQ[¶'Û…M/£à¼íË¿ÚOí¾đœµq|ËËQ> Ͻ®™¾Yáv~=í~\àôˆ ̀'‘uMN₫¿ÙùAMï]“ïö‹öÜeÑ^—-Û ÈQÿÄSøM;:U‡VÑ«#¼ù±3s·Ăqü²b–'ư³è/í4³•À1ëñ'̉ơm÷l3́÷x£O‰·¢x6­.ØÈÉɨxÿcYâÍø²ç‹yUΫ5ï•rËQñ¶\/®W“r]ïÖ§^—Ÿ§ă³ÅwñÛ¸ä$/¢Ơ2¦‹,­`üMóÓù|‹êƯEîưbÔê¹¾>*ΫÏåª6©.ÅËâ´Đ bR1z'5ï•iôHZ²̃Â#/u$´{wư©‚ÍâƠt₫âôä¤î¡8­y+̃yû’®ÆÓYµøCQ¬%ú”WăƠä—|VNW®x›²¿₫íï"8éx—1Xƒ˜_Ïf{›ú›¦†1ÆvÛg`Yplñ®§6MLxŸSÛæ­ư¬ÿà®âÍj1yW‚Dêé3Q¼/¿Ww‰¼BÚ ¡÷ ¡÷ !% ïî‚ï°ädHQødˆîø~­ªåüö훼œ_ËÅ겘,–?få—ª¸\Îä×êjv'’:ÉVÓ&’ÖÈ騶 ̀¦}Qç]k¢Î¨ßÖĂpfGNßSt‰÷ïoêĐÔ±©oøà½û›Z755µijÛÔ=ÓØ3=ÓØ3=ÛØ³=ÛØ³=ÛØ³=ÛØ³=ÛØ³=§z¤ÜÈPÔ:́V¶®ÿl”] * •LüRĂ© l—”tsÓ©èß¾Ẻ2)#œ̉D‡ é¤1ü̉ÊË»QÜƯ߇Ó̉E#tH¨pà1pĐđ8¬’Äoá8!ƠØ̀p6Ê@,¢â·ŒF:ÆÔg­ïUÆ0¡ă„´0!çÜÆ€ ƯˆR¤ &ạæ…(£ ªˆ̀azɰƒ“<.ù̉#– ³`ƯŸ¿́ŒXƒ‘RK¹4Qư5‚t̃ÀAĂÅ¢VüU€0. otç¯;;Óƒ’a61Ñ0&âñÎ_› ©»₫ôuúA(tB00Ư°ñ(^nÀ1|P0Je„‹” ø[ˆ6ôGålp6“/̀N™§ñú°—Œ³ y$M¬KN@2çüaƯ!Ă?Û¨ƒ"XsEÀñ§éŒá³9L₫0ißh”0)ÄñĂ?Ûx2L ̣i£ĐÉÖ“DëđÈ«ÇÏÎt=“†®ö£˜¬~¬«áp†øÛJ…ñ”V<ïđW™˜5&ú ,N¯Öq«éÿSPĐ̀ endstream endobj 179 0 obj << /Length 1911 /Filter /FlateDecode >> stream xÚÅioܸơ»…ư¢)2 QSôƒw“z³Û¢ijX$A qfÔ•ÄYv¦¿¾ä“¬9<Û±ƒÖ€-ï>h¬Ü\}{ơêÏ2 ¢Ê‚ÛUÀ“”0•̈bQp›Ă¯ß/›]ÛÍ>ß₫đ4`”(ªü! M s ̉Â\QÄÿööê·+C8(I"dpN¢˜Ëêêăgä°÷S@‰Pipï + ·K”Á?®₫’@óØ^Ê(%©P€+&4R₫ê¶ËEYü[7³¹ä2|ư'ÿ½ìlÎÂ~û‰JúѯM?QÈ^ú)=üúÏç—{‡†]vôÑ©Ú lOP’¥DF́ ’:6hJ̉äyÂ8‰¸"BÄ#Ü\"wûPn¸ÑăŒ_Lơ1ă4!€î< NXî!†‘§£"$!˜:‡!ár*a< B'ÂêäÈ@„¤?#Ü;4øÛ¬ƒéôĂÍUđqBĂú·¾hf, u¥ë®ƯóÑC‡¦ÁœG$E=ßnôlÎ% W¦,Í Tw_Ôk”˜‹#"6Ä›ë÷'£…$Iœ @Ûlùk¶Ö­¿!kđªÆ‘«ó=2ƒ9đ/D ÔqP Êáç̣€›}ªá‰ï3å®Ê~اM&$óFØûM±ÜxzÚ»¾ÁQ®·ºÎ‘n3l¢ZjÛwYW˜:+ửZ›JwÍÎÏZ³êîglÂ2Rf×49à;N™y¾ă§đư£WÆ£*Ÿ{ègHöˆ¹‚†äˆ9O&Äÿ?˪Mw`bn¶˜qö¸µ)Ö›r7€.Áer¿>gỎÊ2kœ tÿ3ƯüpÉ]Oâ ”óÆ,Oé'’`Å#\©µÎ-t«h·e¶;p*S—Eă*«{đ,w‹•.¸XiƠ‰X€üEù, »(\¢Ö >]/¡°`2¬­•9íï†T˜1 ÉÊe_r‡ˆY3kMÙÛËZ¿`VöËÂï ½Đ36‹̀#XZ7¦ß"¦ˆ†wÖzMyg‰Ó¸äú-»fÿ|ơ뛾,=% }ˆS-U•́³äN,v>×+g­}élẸ̀ÄäI,¾úÖ]ĂƠ¹Ơg̀¼>ă!j¿x’°Øf‰ ß~Ưê¦đ™Êjû5ørç!»MÖùå²Á+‹vØÂ[*ă<–Ú¾€²°Äơ¬\›¦è6•ß\™IƯèSLM¹³×4̀·A…I!}¨Ư ˆ«ư~̣Ư ́Tv ddy2üeƬ¾{\N/ÏZ8q°Đ›̀êú®0}ăᜡحÿê¼@³²$œæê¥Ü $‰Â;@µÜ”C4\v¦Ù½"Sxµmô ́^ÊlË–è”…ï:ºƯ˜¾̀ưÛeÀ³“ ̀3¬̃‰`R£eÁ¬Û8½%ÂVƒô_}‹X'ögô ¬º'́ÈưH²Đ+3„yï˃đ±5mñàÍ^löP­³nóeáLqgj E¹Rǘ1ª¬ëtcëÖ×Ç…+–h"„²³u+g’¤.^ÖŒ‚r’B{¬~E¬HÊƠsªßg ˆ°U=«÷PŸZbtB̀kü»‡Û×}wüs°üx£q9‰Ç\BbSL}.#mÚu¶Ư–Å3m™¶®‹-wÙê?aébzYH{TF2c ƒÛ†'ư&’…êP*”,†4'Ô ¸î¬dơ×/>;2ˆF6Ø`+û#l|ÀEˆ0/́¡s¸˜üc 0E(–?ẲQÊ¿MËSáÚz,ÊÄ%ÙMiC/ơÏ™âP̉6­·gKÓ¡•e“g¬s}J”bXơ™¥kuiE*†„#¨Cw~„ÉØW2¸‡ƒơ@.ŒïlkƒäÚ¬¤XXg•,h´§] ˆ[EăkÚ»zeÎ=¾%ÔÙ »¤2•2Ú—ª]prµ ªâ¡©q($ùˆ*́Ï€̉ aÈñ¸rI°0™œ*-Z[ÆEĐóÖºÉ:[̃Û©+¶D$ B€DaY`wî¡"ó£ựÓ®¸ÖÍr §*h­x,6—áí‚—sÙăÔÓy(_°H">H́ưß₫̣Ë_¯~ûåÍơíơ—7ï ~ùp²ÎpëåíÍ}r ‰Å‰7‡×@0wZÆ{gP^Ï” og†–†“°́X°‰¦™w†é3ÅĐíâ“ĂÄe¦68V@':m&8ù¯ŸKlC°äd7&Àó»1qQ7>`©ßóƒÑdÏ£ö’3}9e!~xÖ^Ë…’$ùÔ 8Uh™µíøĐùhÏ-Rö¹G qƠaº¶U§ˆ.E‚Ö@>Ô”~Ç•°°eß“¹PC\‚_óÂVeZDST[ÓtYƯá†n[|±w4¿m¬kºÎ„J$áäƯị̈̀¼_¹Ộ̃TC°°÷ú}Îb¢D²W·c—¯‡J=jïĂû`Íøëùj,ưưr³0­&̃ß®»Gñ̉—§œ€G†ÉÛÙï& ÉFht•5Ú%4±ûïy“üÓ±ü endstream endobj 189 0 obj << /Length 1555 /Filter /FlateDecode >> stream xÚÅYßoÛ6~÷_!ôÉl¿%¶Ø€uk‚ÈÖ%A_ÇE:3ÂwÛlV¦›̀ª}X¦³¥™Æyb&Y’̀“¹U: ưµZÜÇ3+²È7Û{ëK¼mWqC§̃-́Pï„0$¸…÷!Ñ4 ë´(̉laifÆ¢„÷â¼zu|¡XB˜€ÆJÓåo”e3å„—T‹€C< FL +IÈ‚LFcÜ¿Ë<ƠAô#ûi¿ö“Y¹É÷ă«] H Am|©@”©Úx'ó7é"»KÏÄc,UáÁà (B=œ"î^M”Öæ?X`#L°hJsSENú[›B$«%@©"âJ†éĂÈiC ¯“r¹™;ù=LwÚGLI>U|æơë¤ÜæúdÅë6¶đ^»TÀM 7wf,—–­yÅíxeVÙvưa `ßĂÁ·ª¤²¹Ă›´\Éc¬(”¡mó<ÉÊƠw»™̀Í–qÑ—È;X:Đï³²Í Sˆ7'óµ#÷ˆEñ"A¤ÅhÇqÚă³tµ™ÿ•%g`;{2Û?5 ¥|ÈêP}6å!g!_Jy—b»q₫Ú#¶¹1ôÖœƒ"^ÛÙ*Éå̉̀R7Ú¥.-BR¯̀3/21̃ív̉Ê3„iMy‹½Q¸¨‘ÓºMH¯µióÄÓáŦ 1 b2̣1¾Đ89â¶Ñ@²: ¾”{Ôñ-KT³qè¢Zhsă¬Ø Î~ôva‰W«:>y 2₫<3ËWë½ÇÈ«êˆỗƯö¾ôtbÇ\µÄ ºÁ¾fë̃dƒ9ü· 5h"©¸«e*X*ÜTÙ™ÁÂ<f2=A¤Î¶l.Ṃ¢‹î*l±@C]v«S8§ˆBqä ^Cá”qPÆvư:bÚ‰÷ÅÍ—m uqÔO®Î̉:?½™°¶µƯ£½„ñºƒ[ëï ­=´¾!)¬£ÀVøă: ß'¿£(ómr¤G…Óâ¤̉»öº¸AÛPØkÂê ›ÓUx…xQm¿2ơgï!gsY#z¯V÷™y-¶¢;H‹¤½¦R Å]ÜøÊĂ;PötdôçfîÓ?úø.€ùéç0d,ÈZÑÌ!1•}xø¿| úÓ|àñzàU5:[¿ójnuFr’ÓÖjZÚ±8$÷BĂ•ÉhGètuô8Ê>íûàḷóô}„‚¤ ŸØ÷=ĂôÁuHô~±|ÉuøÎ $?§¶#DB—ú́¾oưú—É„ iUÀ±ép‡b(aTC9$t:ƠÏÏRĐuåV¨Ï©ç¨çæĐR¯se­ß¨™­â†wơ¥x¿‚khæV̉U†u]H]YøXuØ}¿̃?Áọ̈€âp%–0¸BVzé|øT¡!Ÿ endstream endobj 204 0 obj << /Length 2515 /Filter /FlateDecode >> stream xÚƠZIsÛF¾ëWàHÖHí̃—¸2UÎĹ$5®xU.I¨"A€,ëßç5º±7Hb”™ƒ h¼­¿·6qtáèĂÙw—gõ )d&ÑåmD•FĨHI‚ áÑåMtµøáƯ§U₫T”ËëËŸ`=F÷k䪥ʮ9Ă₫÷—gœ¸…O€$RLDRÄ%V›³«kƯÀ»Ÿ"Œ˜ÑÑcµrcWw!¢uôËÙÏ0‚ÇƠ?Œ̣»¨ÿà³×ƒ«È #©´b ¨'•săd»‹wÿtâUßƠT*‚Ư@0ººT,~,~ùă!Î“Ë ²ˆËß°Àø¼ơdÉ´ƒ  N0ÄØ–°«$¦-E8ÂÆox™?$•aÁgs . ¯LaGƒàßé&Ét›Yx<œ óí16©–H˜“`A•hæ Æ¦0ŸåXjÅ‘ä¯ ÁR}z \]‘sz}ÿÛWôœ]_Ÿ³-46²¤HêÓ@CJD•‡Æmœ®÷ c6×±à pư$(2`Æ!…FăI€ ÁÙGs(pß1_?OÖÄCÊg¿w·K€ƠoÓ,Y^PÁ›x·K³»Âưµ½u8u(i…8uÂÍBIÙ¼YqSĂ6^;²Å.^y~áU™dîö1OËæØ‹»Ë.NsÇ©.C(•²fi}"$:G”ÑzÑ;¿¢GH"Ù’y;EƒƠ+¾„„áHs̃…„L¤Æ ™Çû$OB̀(l=JÜ'+X#qÚ7×:Í’8ïm­%]0¡‘‚xA Ô§¦8» É@ ,j<ÜoÉxWÆ••q ±HVå6_ ±@ë~.\Ơßx÷)XèI¤iSçåÉ.O$+kf=([¾-”íûߟ‚ª1€V,÷wS!&Ư₫’ŒØĐÔÀ8†% ¾ñd1Åÿ –›¸̀ÓU˜+‡Hjƒ4b„·LW÷n—iq4àÓ âqG›•m]¯‘&–PÔPóvƒ8(Æ· $4¬U»và o‚Ø@ØđÊÀAÄ®ßŃ¡Á¤³‡Tà)¤6.ÑÁö ̀{Næí‰ü4væ¹Ưæ̃Nëµ»ñî}̀"ƯLyĐưᶉZA:˜„C&˜-•ÆfÈE`¢¡̣PÂyNm̉3t̀¨aε¿ú·+ốƯ¶^ŸÅ¢ êv QË6´÷5Đ­5àĂ}zîm¶"n]<ø’NÊ#&DAÂÉ¡(HZ¯ _ù°['^Ç´¼Ÿ[đ„^ÜÊ&Àªö akëÅEé` ™)̣EF ^ü¸b/ươ.µû́¤{R>.aåÖƒư![•°…çßCŒX×ëï! zs¸É>çr0G̀¶üÖ4“Ä–ˆÔƒđ₫AË€û CƯ€›`(»Ü>ÖÙ§úëḉszw_ö¦1N„ªà®DÀ,…jÊ4̀™Á₫?UqóÉ,ÎËŸokq@÷ưD‡u • ₫"¬ă´õk>Pç{q¼(·i¶$‹,mIJ PïR‘ ]<س +Ø,Bƒ5e'vSˆ©ºWo’̣~{S¯́D׌DXôƯásR>ä›YñMø\AÔÄX@"́¼ÔmÍ ÷;°†»ƒ(P]ư²aÁf_ù´‘ Ë‘Ñ@#̉VÖé$_\̃Ç^‚´€æ˜* ®Ö8]₫T̃Û¸ZØG_WÉÎàrMWæu\øwùÖytøœ ˆæÊ ͸ڮ6YÇûáÓÖæøßwq‘ÿ‚pp—üÍØïIĐS.}¡ Uj̣O™ÇYVßÀF "§|Aid(9à Dn5û ¾@Z'Å_}ô·I©º+âߤ^>ă"l0[F9Â% äưÚbyAŒ\ünwÊƯ®ªư ̣‘Đ2Ú—`mĂ«Ù¦_jƯÜ̉W$¶ ‘zoA¢02XX²¾¬°·ivóPehưmƠaŸ5‚Æ¥›’Á³úÚßûQÓ ºzL(HHÛ]E ¸¢; ¶pÆ?̃§ ¡Rv` TC&îµíÀ'vL†ơéÔ¤Ârê³6g[=¬!ær¼×a˜,̉̉½O‹à´Db(óͬiÉT‰Æ6ªDȽí@¯:nƯyT‰÷ ¦AÅzÜöéÅ^G¯ƒc ,v‘ßÀq°ơUØrÀÈmÊ”‰æ0 TzĐM7ñ.Û0N9đC8íuaÙM’7•§»ñ¥z6đ?û̀ùé_ûk".{f¼ôÙVäh<₫ơƒNđe¤ fØ35µCC¡HjÚ:SAI æ̉]Åóû¯ñZŒ1gN aäÖ£É3ă ̣¢Éó HÔB0°¥d¯s8Â8¸ÔñG¥«o¾½ºÂçäڀؓ|}}’óùFÛ‘r$OsLʨ=÷íÚƠ²RƯ_đ¹»w¹>ï½%₫ÓßÚ ‡ËäñÉ|¡Çzäk²2è‘èñ§¬‹̣†V'hĐsh¢oXuhª“Saj¶aƶÅÉÓ·2 YH1å ̉E¢«~k ¶o9`•;4½hœ­îÈbTk¤^먗=MCeQW7UưjUºÓư`¾yƶ×ÓœóR ×úœ·ÉƅɆ÷¯›‹Éùê,fc_”æ_@—J–‚8‹?̀¨‰qVæ5 6c¢q¹T|a«¿uUAz´¿‡Î[/¶›_—°È%¾ætăr(4\ TẸ́̀É̃—#Q‚ë1ZMjÿ–QÆ»©QFƠyøµ=ú:Cíª`ơitç$88tĐ0™½ç̀Éö`tj¸O)jG$S?O †vRŸ&Ơpdô}—=/¯û.P í»*mB'5ˆ¶³ă[O ʵ‹“´Ôª «É–ºĂí@¯ƒ-µ́6ˆíà­=Ă‚Í]mó<)vÛ́Æl]­¿‡¨\Vw<×+ÛĐày‰{} á…Q· ï— 5w¹DÚăÓt¹£¯T‚ÎÚ¡Í1¿¶,vëø©J·Öª'+´çalGˆVL¤Đ&̀.5°pUW7U÷‹¹ñ7öISJO–Çó…ë =='ôEzB̉ƒX ñØ“zÓ(ÚQ,¬ê34œ-̃XCè½íOLN¢!Ös6¡á@Ơgj8[¼¦(÷×?¡9A} endstream endobj 216 0 obj << /Length 2711 /Filter /FlateDecode >> stream xÚÅZ[oÛ8~Ï¯Đ£²c³¼Jb‹] -¦ºÓN`gÔÉÿùấï3UøD’X¨ æœÈˆóÍÙ́’ x÷k@‰ĐIđÍôÜ`o]©`|=ûƯj)ă@ñe”’Dh*µzv>eTÑM\…û0©Cv>U\…—¾@];:*–%Ù#”Î@R4>A%Đl₫º_Ư†/ïGĐ 11™$T»åZ¦»Ùe0ßy)F`»3ƒÄǼÈ̉ưçt8…Ơ§ë×××Đ̣ï´úT|É—«êO@_m Â^9Ù÷);J‚à“Ñi¥~ŒH>Ê  W ›°¤¾tÜ™tzù·¬ƯK"ÑX8±ơ^Ïú‹‡ṚôéK"¢ô3Q2‚’%â±”|“–yùv•á2c$nøp&&|Â.'3:ajJCUh»œ<_O‡nˆ~,I$Ÿ„¯XiΓñơ4̃öø;̃{”íÙÂ=Ê^ùpÆŸ ØæŒDJÜ-‚ èKh´x´PB9%¤’wI’NÔÛ+Ÿ`Öú!Xz/LDÄûeNDÛ´Ël¿¡À_̉đ}¶ƯdƠ₫¶ă¡í(C3 ¦\îm!Œ@Ø)ćÓMàAÎá9¼ÿa¶O—Ù×yº³?gI¸]æƠ;[Ư¼Ë‹¼Â½Ï¿¿·m‡]GÅ»G~ñve+Á Às†‡Ø˜%‘í>¶êC–Fç«ê9 ¶NÓ¡–¨¤qF:(‰‰Ôü1‰D́{ •ªc«&c4!øßô¢°€«íÂ÷ï­b#}*4F*˜2vkù%« º ‹̣åX$'c VâGûz»A¶äós  wÛ2¯̣sذ7("³­‹́OJ9BcŸ7 L¸ ïđÛ-DBDaj‹F>9 ¦¾Ü;* f°/À>ơîN'"I³`z„JÂj•yÑfÍ›1aIí°q¸½¶ÍuçôœS7mä‡m, El}g‰ḅ̉–{ wXd ¦.̉áÅ ̃l˜HˆˆºØ˜ï¤pĂB¥à”L¹r›Ï3̉lWÏH|È ¨g ûpuÛû̀đ´đ¯í₫sVsè ¡¼q ü×đ¡È₫†Ơ+’•=ăƠEªgÁ;ßU‘aºÏleŸí’¬¨P{Ẳö…™VÊtăjßpƯÓÛæ=l§ÛQy°gk‘EZº¶‚ƒckÓ¼Û®o7é_È ‘¥W°¨6ö@+pK+ÔÙńyfÑ|+â®%5ø}GƠplIpÜơºñ(’$R‚(p>nW{9qW„À½ƠëDÔßK,˜-¨/^SÖ=U:VUU±ùTéøÊ®½ª7`Í‹²ÇơÜsÉm:j­‹Áµü.—GL–~ØƯ*0´I{†? OóûFëâÉÆ)̉Ăóûƒ4g'iƠüeH#Rç”Ö–̣(́>rÉ1r= Œ‡ÉêEO}Y£6tÊ!€n`IO äß䥱µe¼ơÁôgŒT¶yQ}6Ö.ß?k =Đ ,é-FÏŸJ ÎÑ™%˜57™%‹Ă>35±]é©°ǽ¾P̣«8RÿŸPºeáƠÁËuV,}LƠ›k M7Tù†¡º?Ú?ØP !½€ûmºÖi…®“G̃F}K¨ëHc NÇUº¾]ú„·tœú=Ø 5å.;‘ómQ¥yQ{Ëb°+*j¨0M)p¿ơ¢—‡ùÊ«V£Baư)×}¡½)qđ´qoJ=9¼í†Ơ·B=£Ù.Ûï²b‘ăŕmô½ø^ôWô|ÖƠöŸ™u§Ơ9„-(k„öùëb1:©Iw̉ÇLéi‘¹K rùÅ8‚ ¸ĐUM©æ'eç”T½pûîÆØË‰Y+‰Î, ¯­¤ÑŸD"«®ú ÙÊ‹ ¶E&eÁw¾Ï¡4³ƒZZZeœV´ÉXñÁGé@!~‚>ûogFªj¾)«´X¤û…Uçq“XI¢Dv"L9*äXöÁgîU±u óU6·Y•_™ë#I;ø<΀.₫Ăμ…-ưáŸf2‚DyÄ Ë¼đ«|¾ú/²O׿ ÑC¶gơ¹C-¬Ç=-d.”5–Đ9Zôc£ mºÛ»r‘¥“x×Óà˜J†«= ù¨üöö8.B®åI¸Ü ‰hN©>èèªÔ :î÷È̀îTë*[oqo}3¹Ô¨~›M³ßa­Ó«Ö•=81fEqs(̉™ĂǬ:ÿä7ƯNêäö ÏdÀ«â NÄ:6›#¼¨aơRˆ¤}̃4Ñk"’ÚÖ§̃ÇöWƠ¨Ơ°¥gÓb7¹æÜ±ƒá,:ÇØáê¶5KÚ›%{À,9ƒ́¥ÉĂG3́˜H¦zéÖyÙ¸m¿¼xvE¹è®ïÅ*+ƸÉyIü\FKRs1º;;‡’¶ đ O©%·ÖÇüđsvW[ǹ›Z±åv}¨rŒó°Ñ,"”˜,™“FÚ#<_aZw΅çÆï/V™ k"óÚ <‘ƯØ›rklr KÎîå³€$–µ×¹¶ç¯8X %CmÛ(£äÈû ß @^j¥7Pb£9M|ü ]̉ca²$Lœh7í”̀h~Ú¹›±‹¼²££Âå¶±¿€xDËîî;§…ÉO\$·k# ^N 6­ö··¶t¿5”¹OFÛ¬ơAJY N×v×víưÄ|»ßƒÉ*²²$Ă_zƯoLC. Jßñ)Ó1Q&ă;öÓ8Á`‹z2’ø«0?O7»u6Y¸ÊG =ø‘™%(úC?2ÿ€¯D Z‚û–» ̀¾nTáEÖ!V}R„íö´¯s\NfxµăÉîrœƠíHOq—XHXܽ{ä/VLyï†Åñ˧k4œ”&‡ A.Íù£)„Fïå?ß Ñeáà4OB¡½}́Ø"’¹4›©‰„9Q—OH­“!®‚d+=É5!&!§‰ºÔRZ̀ßâ™&÷“ëd†Ó‚\;æÏE.!ˆ`?D®ÿ̀øD S.ÿû{Á7OĂ“qBÉ ˆŸ†!à…rɦêœ<æPmª y.PHĐé£oÖ 2Àe)ubMIîœ×ÓÙÓññ§*®ü c¦[ endstream endobj 229 0 obj << /Length 1319 /Filter /FlateDecode >> stream xÚ½WÛnă6}÷Wy’˜á]d H·I6‹E:îH󠨲­Ö–¼–’6ß!©«—öÆÛ¢ )™œ9sæ*,Ü ¾Ÿ.®… "¤#L‚é" ‘BDGA$ ̉„Óyđ¾¿¼›í^‹rø8ưçq@0̉X» L ¬4ˆ³Gµ93À•ü«éàÓ€À®€H1D”".i0Û q0‡ß>1­‚¿́É9 Ú…ÖÁưà'‡’GFZRi”j8¯@"•sí4«¹§Q…'_¡̣sÔ`²ÀÑ "0‚×öO=»eĐ1¹9báëüe¼ưΑjïƠR¬Àî <Œᯫt¶ºOçÉpDÂñâưë6Ùm×q–ü~ ô?ŸÎÓ,ùïÈ·•ü/öºµ!ùd†>#Yj%₫›ĐÀV…>§«ô HHv\E8Ü—Đ¢øjBT ˜äÇ$pNÅö]îTe5äƠ¤@àX̣(bH́î‡G|cN’u\¦C‚Ăó/¹RæEZ¦yæöiV^fs·_¿.ó¬W3k¹¸†âÔ)?8Qx"XäJ”âƯ3n[W(‡ï%¹k0‘’ƒc̉ÄÉ!@WW2Œ̉Z̉Ö\;‰`bÖ¯>ơ’"ܪ7ùÖÔѶîÁ‡{í)œCÚÆa}¥¡È¹­Ơ0bJ#%¢`DÀWuAœ$åónHD˜ßø*79•Æ<ƒrA¸dá3‚aDµ¨Ÿưr5™^ưvf—áÙơ廫éYEÅÙøçéưíWͯ·?ÚG†Q!Ι.œđIy€}DiɯÙ̃ëG 6§À(ÆHûl‚®ÀdăMăüMüg2~ú#™y[¢è8›ûaê®T#>aŒ!,¨ˆ̀ă.Đï†B@0„`áí«Gp(Ë́mz/§EÍGGß®L̀ú·{—ûƠA ơeöR¤9À ËU兢ܥÙ̉çÓpSÈ~×aæ^ 9¢=»4 w&æ³dÔAi>D]„Qâ-ÔE´ax&•’4+LsơIT09Ê’‡ºXÔ¤Û‘ :΃y"6ṬEµ–n­m"`“{»eaJw 6°v²¸\,à«äùÚ4¼ßÛqö1Y”ăƯ$]®LR"N„‡ñ½„Ơ0lènÂFÖÖ#ÀWç¨ë–ÊtØYÓí) ..‹Î¡ÈUK ‡ZöW»FT« ªƯê»đ‘A剦Aûă0@LWq¥'-L/65Ư=Ào²iĂZŒûlƒß0•Ø ®ÄÁ¦êeưCÇM>^çîb¹‹³†n ơ°@-¡Pï…åtU÷†z«úÙ úcƒ*|)v(œ¶c“À{áÔV“öóö¯Ă! endstream endobj 242 0 obj << /Length 2250 /Filter /FlateDecode >> stream xÚƯZKsă¸¾ûWđ(UY0àÉlỚÔk·6ñf́$¯´DK¬P¤BR™q~ư6|€¢g,ÛåJrp„ÀF÷×t7Œ£u„£‹́Ÿ?^Ÿœ}â*¢Å1Ñơ}$c$˜ˆbA£:º^E7³›dפƠ|A±ùíơ/'á¨ư«ÖÑđơó…'Ê‘T’¢8Zpã‡|]VY³ÙÖdyï—Ơ]Ọ̈gŸ!C”P„B–ÀÂ- 7%”¨vÉU“ÜeyöŸ–íë¹ä³‡]ê¸÷̣Ÿ}8"i¬-‰z4ÖÑB0Ä¡̀¥HV4U¹Ú/ưkâ_æÆî¥)Ưs™äË}4á̉z?§bö;Æt™¥EăfwIƠ„H$…·ˆø©•ßaăiÖ#»=ƠØER„#ÆcêƠÁ"N>†È4Ư,Æ­,ư1ÂV²̉¿|¬€½gëḾư=CÖrh †3xk Ù£«øp¶vxÀ̀œ̀FüüöVE@IÅÓÔºäNç Aä́ëÔÎ\ ¬;²Ä­#—HḰˆJø w%³ù6m6åª]?RËÀ;˜~D´ îcĂç´ÙƒVŬ¨Ï»Ư†l†;3ˆå½¦ëtd₫mÔ–.›²̣qø¾*· ¬^q8xKçfr+0TÚ®đÖº@\ˆvÅ»IS—ï¤"SŒ4zû›ïíÛP¡Àö`S[I8*t·ê ĨMkœ»*­!8×£xkq¶ ½Å“„­ó×´™öc‰T/Ù¤‘ÀèÀ;Ø‘aj"9ĂdV%MVIî&{µ¹÷Ç´FÀM ÿWj“R ƠfÅIÄ5Â\sR|dg׉ƒ³̃%ËÔáî¾³³Yám`ËÄÄ. }YmÑ"•˜]o¼Îî÷Å̉¨ËÙ å XđÁ f‚E™ó]’>K0¶&©·5øÁ§0e½füO´Ë `®µZ˜Í3Gƒ«u¶JG-ḙR üÊQÿCF¾o$œó±‘„hÁ~x$¸kÈú“ü)Á}Á ˼¼«ÓÊy©3¦!`c56‚Äh‘*X‰“[_=ø©<Ưºô^¬ÀÓ±ƒû}ûŸ¼-Àp•Ù́>µÑܬ2qÁ÷° ¡sHVæ/̉ƠÙ²È=Ow!µ}å¿mª¤¨s£\t$1̉ Ü@Ü¿”÷*'8Ă>²Ú—ÖM•9·qkJ·Â²\»¹GăœäˆÇñ+˜0ÿ® ó7‹sq`ÂÛ䟦ÈH=p:Ơ©C´n§¬ÊÚŸ7å>_¹ßï<ÄËr 1%]¹7ë­ \ ¢ ³éPiĂ£†*S¨Ôµµ©&RPÉ ̀“$¿úN&ă‡¡‚ê‹÷‰‹ḈjÄ1œØÉfy T½¯(ŸÛ¨öІ†­ÚzÊ , ̃)EŸ ›Èktç2µŸ®O₫ub8ÛÚ˜á -·'7·8ZÁo¿@ÁÀ@Ï_́Ê-œ? i¾Ë£«“¿úB[Bâ¦c»À«c1»íúlwyz¸1å(KŸ±sÀ½´Üyơ·hàˆ"­ôAØy ÏƠŘ›‚«=‰¾0@6¨ỒÄç‹ Œ!~3E`3ȱ½E¯“Ư¾”4Ÿ•ßp•“êƠùû+“\̀¨ !0FÂN…±‘wïFeéc¼µ‰| ƠÎăÁ8Ĭ)æúđT&±Ï´ Đ©Ừû²øêô†œÑS|ªÏ¹µ¿ âGĂuˆx,Q¬Ù$ÇSD}¯*cÛ°HùcØ Ïß»çMđÀ§îi0r# 8¹Ñíi°´_̉~¤û¥Ư‘§ĆhqƒRW2ơ"ÄÆPJi Ñ“zfsC¬.ª̉˜’óØ›CüøŒŒ é“vhµúà«'€}4R‡`s†¤z™yNQ,)Đ’Ÿ]MÖ ”ØTȻӴÜG3}(7#HQơFAÆG̃*bƒøcàÑH‚ e¶’¯)¤|B¿$Ư1ôÊǂğ¶ ”_Ư˺.<|±i6>´ºÉµ™L‹´JLắ‡'ÙơÑ8M@ •¦â/ÉÚ^@Â'¾†B¬Ä·(pˆ‹0ñ7Ñaî/Y~¶MxöPîÍ@Î[\ Ô©)]ٻʔáWnÊd́µºf‰lÓÿØYÏ©I₫YK<-Od_§SE )°ØU1·ĐŸËƠe‘NVkæö,h¨ư*ËĐ?aÂÆEpö‡=a_:ZNïmå5è.©ưÈ•ó®ÁÀd¸£ƒ­ñ8×î[3h[Sơ”Đƒ#ö×g›́0·!ê·ÄTn“•67ñóD7×:zJôÓ)ö˜©Öº̣ûºo9Ô×她TIMÔü z±ú˜£™¬,!Üè₫Fåx† T–ƠÇ#Å2¨(»åèH¡₫R$æÇ„™́5iđă`MÈ#vf:ÿí½]×́ŸÛ繕\DºÖ7‘ม­]íw»̉¶$„6÷¡³~hjuÓïÊuu`vp7j§7~µkz)ăÇfÆÿÔu¤̀\Û¬ù,ä\v^xĂÏ Fƒ?yÆn'V‚ÇtÍÛ̃²bû¥+¦©§Åƒ)…(ă1µ‡F·ËÜ\ÈÄc7µ&Û¢ŸƠƒËÛóG[„*»üuZ„ÂJ-ŸØƒxÆÖ§1×»8~Éiö-æ~D¼M¦H̀ÙÛæĐÿ=ˆ£Á8„ĂI¦ß Ò!—¡ÏÅsw₫̃ƒ§¯„ăñ( ÿ' TCzơäHkŸ) `ấfM½ endstream endobj 255 0 obj << /Length 2572 /Filter /FlateDecode >> stream xÚƯZmoÛ8₫_!à¾ØX™á;©]`[́öZÜ]{M®_|ùàØJ"¬#ee¥/÷ëoø"Y²èIJ ßaQ¤¤)z8|æápf,ƯE8zwöæếü7¡#……ItuQ%W‘’%„GW‹h:úë/ŸæåU5¾¾úÓqD0Jpâæ3˜$ ÍN%ÄL:Ă^₫¯Wgœ™‡đ‰‘¢qI£ùĂÙôG xö!ˆ%:úfg>˜Ù°¼Ñ2º<ûçF0lÿ„N¢̣.ê|öûµ”H*^ HÔ°&•óÄ)w7{üÙ©g¿WK±Û 0N£ââơÇ̣&«.Ç2ªf7Ù2ûOZ¾Ïÿ•gƠÛ§›ô£Ï?gw÷Ơ¿±À—ñ—t^åß‹ÅÇܰZ"‘…lZ¢ÙódÓMO½H¶Cç¾H̀á›ïă§8’üDÄ”J#JỡN“^¼~[äó™ui>«²"7đoÙʺÉ"Î&?gæéOWå,_-íŒƠUñ¦ønÛGñư@ê¿WÇ¡̣`û¦I­Nd )Ul_SüÅqóê>[¹^Ư~»ŸU¾—ºvY¿§ ׿-Jäzoü´¬ê X©1ÓZĐrṼ¥G1̉`„ûFZr"# Ùû¼\BLaµÛº÷®«ñ†÷Æ·Q`ó4]dŒ'£,41én%$86©_ä#9ù‹|ä;đ‘>ÊgèÈáFd–²v‰5º©ƒ¢4Î77ñ,«yè<ÎÊà a-×É~C!¸̃ëy™·Ầ-dÉh>2Ö¹ûèÉ3VÙÙổqĂ×̣‡;& (]¦p¼€Ă*iümW EẉzZ5†¾Ÿ­œLs–4ĐªÈƒ²×¼±Û$$”fͪỀn,›-ø,¯̉rg̉<·̉·¬ºwÏœ³€ÎW½\ *₫́́…ØÜŒCâ.ÍÓr¶Œ TÊ´̣ùKÉâ·ôØæEU3RELsüe¹̀¼'Ị̂U¶ q(ß̃—/+~xw¾¬äNw•Ÿ5/—i•.Œ¥đQÆfeÚDÚB²ÎÜ3a;IömËyÀ&ˆ1i…È ~ư>3*ôWf>Ä {,ƯK}8\cJ’CRŸDÔJ04D‚'I¼9¸3–Đ½ï‹×—³yúÎ2La.k‹ă•›†£Ñ̉+}*<)¸&¦öų œ ¡„ÓŒw̉»Ëx:Å1ü³ÅêúäœÂ§ë£UBĂ×7ÖH'â…NÀÙjÏWHơlpèj¦.B1Ư‹×Ús·™|\×m°d·̀j&o- ßo2“'ü Ä -DF8;SªöăA@´€kAÁGyÛá¼—>ƒÇGƒim/à»1ƒ<Ă ¾ A†ï§‰‚˜‚†C³DI$ë|²+¶Ï̉»²0fv>p°x•ƯHµuövô†n½ä™Xv¼(¤;Zƒ(¤́̉i2̀ÏÔßểÉ76¬³Ư¦¦iđû( °–‡DCˆđ% `–Ç)3ª̉b]fC ÁŸÆ ~Ÿ†¬³J¿›».í|1+.*ÇD :}Yø“SÎê5&£€j>J ×…)äI¨, 9¶Û,dP~h¶\~…¡lkBD2ÄỤRÉ̀€“ÿMÅø²W²|ºéT-ƒUYn™íEô0Ø(3D[E_Ç3̃\FGó÷áƠ(,Ơ«_$ë­)¬$X›ÊD‚]]ß~6›5m§kf˜zaP–À=ÑlùkMƒà† D>É6,¼nṛ2-nJ+j> '“'cƠkw¦_¸¢²Ùsu.Püº/,™­rÙÁK‚¿µe;à"Mÿ,ˆØ]P½bÀc îKwª¾4̀¸4¿a¬²•­q°W^e¥IĂí3W#k̃úÁ°Né5÷w!.Yw"5úGQ¥nAƒSü”/³ß?LƯÂƠ½Ză]øß.›eâ :àÿ%ß°ÿlyW”Yuÿ°ëzyæOí¢H}Ï”u|qư'm£²î«¾v¬pm«Öăưư‰̃ô 2Sh/ן»¾cưë!ßö … ñùúÀîJ̉ơ ñb…døÊ½€‚(Né!!Á"j%À%py¢×G(đ öÿ[ FPkvr¢W£(†À4ÑUH>ÙÓg~Uú̉ À̀x7̉q% óè:’ØHâc ?º>úZ€ß—§AŸè" Oç¡\Ní»gS «7јÙ&͘´­'đ> stream xÚíZKsÛȾëWàHU£y?¼ñV9©µâ=ÄIÉ…ËMA*¨AÙίOÏ $ˆH˜É!Ơ€ƒAOÏ×ßt÷ô'÷ N.Ï₫|svñQèD!£0Inîªâ*Q’ Cxrs›LFưđÛ¼ü¾ªÎ§7¿ÂpœŒ 6~<£ˆỈÜPBí 3ä_|ä:! JjG9#ˆ™Œ™@Z ÿCqÿÂIü+ï“íŸW—gÉdL0Æ£Ïå—¼úíœàѬ¬>Ï©ÍæÙ꺷³̣öú ~]–çD–맆Bû'¸øhÔöâp2¦đ‹0¯'̣h¾=Æ?Æơ{Ơ¼ZN¥s2jjưö¢ YF!†yvo§çcAÔèee•}[eU躳dU§RY”ó‘ÚvSK†4ç[ƒđcV=,oăđ+n¤™‘4†7₫û«¬ZäbT¬̃u…+D@L˜íôSGË;ß®Ö_`-«º³ Åaºjåï̀…‘¢ợÙ@YI'´©ơÍCæœÏóơbVeáwơe¬I›Ê΂ÎÖ¢₫Ñ™* *ÂÛz9e¶ªÊ|^e·Aô²)f‹;GmX]­9S5ÿÔ ሠùˆR¤6¾Arb5²ÓHr¯Qè#bϳ5u6¯–åÊ’wkDgz$îRJhd´j)Uø6[dY±Ñ¬k6m‘ư);J1cm^tm§1đI&½ D÷V‡ zƯÚê]S#ă4Î]ÚSÀZS Á¬̣OO Ù?YÈư»,txF†wƯ4*åÛ@Hª _̣ùƒ—=_cO@f`ëè­³ÊW‘à`•¼̀ß›4öÚ¿§ ¥@Dqø¦fˆ3ƯỐoËÊnKFœéºXäÿ²[ÊuÆ o—đTvºOFm8u°í—|‘ÿ;~ÑTN+„7 Î÷Ë2¯W©‰Ă”ÎÍÀœ·Ë,<ËÊëSf¬¾¨qĐ2/ÖUè[ú®Eå…ïX-3Å8%›8X åÖ©•̃RÛ&ªœse!¾5C¶ÖI7±Z«?·WÙ“ ̀`å¢U¹}ó́Œ³úäAé́ܺA§ó³Óµ¥' Ø̃©ÑH©7„w¿é°AR³¦I÷Ä|f`Ë“Wb>S ŒÊcƒ¾8$æx%Üu- œ«÷á¸Ó}c®CÆă í·Èö¼ ¾': ¬ÙÍ[B ƠÈ·Ú…eø¹Zä÷•~vÄ,s0¾ ï0*ú³ËôÆ ;1ÂRè­1rM·í´³é„àM̃Û·ñ¶óé`̀H·cÜJ«¥ï«ƒư1 ´©ưk-íNˆ[0ñi@°ă2ø™ló¦ü̃J¢BXp69ûåǽ3 ¬H0‘p^̣d₫x6™âä̃ư ëcF'_ƯÈG—( e¿[$×g÷ç8¶€£’Ànw1ˆAÄæÚö)¯ư/ßfO‹¬=3£̣sÈÔ ơ•U_ÛrŸ œPHtLK‚ Úe¸GˆˆJÀ1NR²_‚÷̣AÄ‘@l“YĐquÙ2 Å4¨ XS0¾Ÿ=ư¨j¿k¸èí#0åúƯ{¿ÎÇd(K…éO?í̉₫å"Óf­ñ́FPH4$XO¨TÆÓC­½ôSñOXàÄUûÛß<^§“ NI*́«i:!)Mñt‚~oèÚè 8DœÍs¨ lîK嬲hN~̀tBS–’€©t­í'đ>ơ˜CË.Dª|?µC.ˆJeJ.ètj·Û ƒØ¢/mS@¡Dk¾Œ4gî äœ;› N}KB+|3M£â[êZ>ÂaTçàÎoÄHvoYÔ£)96­xRĂƯ¬6̃T!}"æ3­Èít$Èă­ ¹ö8ơĐăôĬ :HóSy{™;#Ç8œ.†ÿˆ-Éù¨èœ¼SSSï¥́«á„§a IÈOÓn>rP¨c2Ó‚üEwÓ]mh„DXç„ œÎ• Ë ):½pDï¶$ÜÅï±{të«7ÆûSÇ×<~ü:LÀÖÇÔ#—J:LP¤ỡsçQ,vJ:Rtf¯ ”ÙÔ£ezô¦Œÿ¹Ø>^i¦o®4·TêÎØ^Iu×TLÑWjÅ„kÄ1ư¯ÔǘyƠq»¯`ïl‘Ñ ƒ\íw¯o­¶Ÿ‹+[Âê&ă0G£¢y¹UÇ,bưÓ€#v;ˆĂÚĐ–n«Àea]_k9­]yëÖÔMUÜnÍ)ë+eè¹ßÔ†[wf‘ùî_*"»ͨoSĂâVu È₫º[–öJ‘xG̃Ê^¡Æµ¸ô—₫ÆI`—7ï7—d;÷L³j§úŸ;WPwëÅ"\ÅÛ6™-ËûröôÏ·HđrƠ˜2È5‰¦jLGè7V˜ºå¤ƯÿÑPuŒ—>BDT<—ơ 'ÉF)e Èz8¸́®:\Ù¸?mD1øP¢N„(¡c~(¢Ïï̃·r˜˜ă ho4Z€ˆ,\¢Æq}( + ¨sˆ–¢])‡íßđ—éäy:ØÁ¦?Tm´5G«!6DĂY„û÷?Å‹Z Sˆîöñk^=„óax—®lXÎl̀üùå<¹¿¦íÅ*l¦yj˜”°Ă©Eß½ÿ́ïTÉVù©ødMYq ṃ`Ö³å Ú¾…áĂЬ7lmä%Leä 4“ưăhÖ[Óöb!­–üD—Y^”A³÷«aH̉{ÑmܘDRCU$U¹Îö¼÷¬3$ÍQ©Ư"Bzl%p£ûœÀëóohÿ §}Ä endstream endobj 274 0 obj << /Length 2214 /Filter /FlateDecode >> stream xÚÅZ[oÛÆ~÷¯à#…Jë½’Ü=@Z4>( ¤'Ö›h™²…J”D9É¿ï ÷"̃t¡¥ă p¸$ggggfg¿+<4¸»ùu|sûI%ALtLY0N‹ù*ÿœ™?¿Ÿóû¬ØÖ́9®ÿö“«s£ÁˆĂÆLbæŸÈªŒiºé£eΪW´fÀ¦Aÿ¥MŒª*ÍHEN×ófµ[#Åâp›¡&{3_¦Ï>é2‡qKåtÀX̀GmdĂ@qEˆ.³âeơäÄñÛ« °zÄQR»I;ˆ‡ óíÏ])"cÂ@íălÀŒIy F\Ñp™›ù·̉» F¸=@¾Ei¦¹¹f‹l 67«™¹/™il×é´lJăGc—®M†Å”á »ï²=!‚ 'ñơe>}±¥— ·mëẨˆm¢`:>,^ª±–(.'T¬ÎÔ-9á‰_ớhD"‚µêÉ`$ c§̃û £LI,t= ËƯ¶0{´›çæº-̉ü)Ư<™»Ùj³4-xjSÛse{Ø9Ñpƒë¢ ưÍïă›ÿƯà4Àd¨?D DRC̣̉`º¼™<Đà ̃ư«U@ ¿–’KX51Q1ö[÷7ÿ1% *tŒxdJ†8G¥2Ûóû·t¹^dí‘g„Eú-C×̀Kóá ôˆp¢Ử X®g—¨pFI®k05ڪؗEjku|¹ëp2dŒ€$ŒDB$‹lK×ÿ²eûƠ oơ)í ’ñ₫ç_îqå̃ F,Ä|ÄÚ$† Ó‡-âq®xƠÂêưÙÛm‡rN’X¾“CyD$́¯ot¨ßĐ¡nSªîHøÜíJw¸Á@§É„áßĂ®́–£Ü= ¯âÿ̃Îkû+{¯„f’(j‹FçK¦u8±₫4jƯ .µ-j.Ăn¹†”½”ká*¡èíÇV(”NÀa}¢yØÑ”eưÜí·‘wÈQ÷µÅˆË–Ôˆơ »¯©½¯8¯÷wY‡×lMê’måvkF qÓ ™PƠØk„À)‹‰b¹§I:p—Å<¶ ÅÆ67s‹;Öé¦Á #X¿¤<hx€÷:à̉c©§"Aà<_¦1MÓƯ"-2¼M âÁç³ƯbaZÖ>l>8 w…]å‹ïæ±ï„öÛN3s[á—»¾–ó/‡]e`OçPø­]Yñ5Ër ksQBÓ{>@i7–±' –VÔ PG%Ä/]:PÂ#\n!¿€´V¬6=v́ˆ ¢…:9’·…#ؼ>v¸³’&&7̀ÓYVRhæuôël Ưm}ú₫³Ơb±Âp|ơïf»¼Ü·–N62¬ ‹¯̣ư‚Đ=ÄưË|f}FăÿB‚Ùó4¸f ~̣B I„çWëƠoG™Ă{76V‰$1oPÎJ₫Nw.Ûw¹_₫ÙÊK¶qùÀ&@1V‹q'ùƠDî>L %0Œ˜³ëPB) Y¸<“¾aèÖ̃-…‚iˆKöî T8# ~ª8y-9¤y$ßL ]-AR©'£LØ-¾âHUàO< GÓ4̀® ÅôP ÙĂơĐs¶Ă¯]=K¦jé.ø¼§Ơ–èD·Ư²ü(¦Ư4å0î?í–ç„Öå̀÷I`*W×O`6„íæ] |½¼íﺶ÷“˜Ä́*y+4tæ­đXk›eứ˜'îƠê TØư5O½Ï°ßCáÚĂJF{àÊñ –á&Í·€zÁ‡«Ïyö@‚å‘̀j—?ưV‚wœăªUh`GcỖ sÏ]ª(h²³iCYHä Êa0\ AƠ[èŸóm‚Ầ2́₫́ÈÏy˜ôePJvhL7í;•‰83ˆŸ.Ê1±…câ5E¾‹Úàø :x©Å°à»ÂF4ë ™à INBJà•\p0’#¼-u;cWß:Ơ 4A¥j€L}^ß~µ„@FŸ@?AÊL:‰6,H©“sxvt’g÷a¿'u|èL&đ¼:ßoú®¦ăÁŸÓíW À~{ª¤<†^Éu˜êb‰8“ô¹µÙđv Í/Ùl.Pገ8̣wÂU<`3z3®̣5A’«ûƠ¢Ï]áw€Ê„ ¾2üáj¸ª¿ëÚ̃W”$ÉUpÇ>̉Ç>§Ó³¾sư.áu Qí§ôzûØ·ùëËú;§í_àï¿Wv(SÂüß³r™•çu˜ÓøêzyƯÛim¿óèÔQúÙy-Àj•tåuëÜgtö™L;æ;TrW¸@…ÛAÉ œÏ˜$J*Ÿ »˜+üj×â8z¹2đ đ,f]<¿E;¬XOEDÄüÔwh‰XJư˜ïĐ=Y€=÷h|Ζëâ»i–ÿ W¸›ăq‡Q˜ă Ss©|¼îø1Aíqàk7.f{O—çCí†w`«> stream xÚÅYK7 ¾ûWèØ^4ER°¶-ĐA²‡´‹̣0 ]́Hÿ}?½‰g=›0¶ÑvG}¢(̣#E³rH¡æUBkxÔKÆí*x¦@¹£ƯB©öÔ ă-årÚt‘[µ$¼¦P+¤µZ†(UCsè ̉„Î̉4ôÙTđÏ–Î:₫¨̉ÂÖ,˜;¦éç„Đ`̀1lĂ J1¬¢aZv «Íè¶%Åënºç´ ”lcÈvQm¼ÙúœñfœĐĐüAªØ|)è(P–₫ˆ0’#µ!S-Ơe¼-b您(S .&Ï0 aC¤ÚM„×`jjÙ°€5i£±©Û[¥³.ˆ€é¦ Q(©ŒaIÓ€! ,h`ŸĐ)”Q-dû$xm{đOøŒ°hx *uôđ¬6ÁƠtĂ*¥ªMÂP3{À¥ÁwQ¥7kàL¶}0ˆlWØ+VÊÜ‹-åXá {Qj± :Ø@ƒjÄ̉ªRzV³Æ;à%%H$A$„à/ĐmºT4`H‚íD̀¾àˆ"DáS’‚Ä›¿¤™ ±3é¦:X¯©BcØN³9 ÙĐÑsØ™~ÂZF °¾˜#”Đ0GÀx*æoÄŒªÉA ¨J]œ-†gá2cÉ^„áƠï„ªÑø*cÁ2«Û_/=:¶P„»<Đ"y|º°%Å ĂN°çëƠM8; Ă9[—ͬs‹M˜tÓAP˜i7fÁz7b¡ónç o;–¶:œç1hi۳؇£­%†çWëw/—7á2 ÏŸ‡ábùé&|Öï⟿—xóçr1<…®ËƠ͵ŽM_ /–×ëÛ«wËë1¯~[¾ÿđæÉúS¸4U¤K4W"?ÄÖ_cµ7Wt¼Z­!ñr̀Œ¦̉½•ÇñÅđ̣öíÍØÿơĂê¯Åđd}ơ~y5®^?¿ O/óØ1̃a3œk¬#Á¡€…›£Œ±5ràf†ŸÖë§ưp}ûö“?¬Wd‰ùG³ÏOAÔ/>•ѧHÖ±ÍPeƯ¸_[½4VjlˆÑ‹ú ÜcS¶¤ CuNĹ“‹!ÚùåÁâđ‚u塈A–±ä=$;ÿZ`Mbi'| ‹¶í °Ø1Kó“®í[°–Sj.́ƒ)r›%æâÓ[‹¨RNUÆÓ©娨X\ØDQ|bq²ÂƯ‡-9fö©€wÑTVr*“™DÂä́˜„E¶º³ËÜsüAB‰ïGŒ• ß1´Ùܬ uF̀z)&':µ“CS,́¢JŒÙ·1ÿd†sX”…‘Ùg½±¦zd’Ô+_)kvI{¯¬Ùeúƒ>”¨wơÊQ3IÔ»Í;ˆ:̃ƠS->,̉_/ơôX 9gVP‘q÷—˜z÷a…beơaµøtÀ%â8̣a­¨©|̉BÅ™‘¿RèO‚e'¦Ú+óV{\ »¼™B·ü«=RöA‘)¹’ +5!U6–Sls”:K8‡Rÿï)u(;˜öØÁév|¹Ú'Sɾlmû́§½+R´đè)*n&\4æñ«.@ú­›"á®H»7Åăt!iTµû4(¨´°p¨[«ß̉i(öÓiĂ µe韵‘ Ó$₫mr::Ç‚}̀Z¢Øg,²˜6VK,¥¹Ô¹«·ïq̃ ÄÙ}ÁĂhÔÂ>,µq‹,wx#—ÓcáỡªëjaU1Ï^4¹[Lµ\4Dö²“”#³“Đ)³2;º-ä́zFúé ư÷Éj÷©-́¦öº=13î!stÁƠ´« [ذâĂ¢h́]₫Âê!:Ê@Ư¿ê*ÉÀíW擃¸!ÚOi¥¤UµŸ j$"ù>Ơ×âÏ®sXœMö+†+ÇdUÖÁ¹»È ¶ t¨äÛ[Éà‡x‡°ù)´î¸~Û^ù_ưô¨zü \¼¬ƒ endstream endobj 287 0 obj << /Length 527 /Filter /FlateDecode >> stream xÚ½VMoÓ@½ûẀ1•œÉÎ~¯¨zâĂ7ăChC„ÇÁ ¢ư÷Œ½v!¸ rrˆf¼3ûæíóSÖV à*¹̀’Ù[ăÁap‚ û ̉Ôœ% ¤!»…|̣îÍû›ú~·¿(²kn@ƒ±_IT–­m%Ư4%¢ĂŸgÉ÷¤)̣ÆD£ 8iQj7e’n¹v Uđđ³í,‚Că}kø”|ˆ4™UÀ`¥4*eŒéĂçw‹r»^¶ &+IH6¡ûZiˆ h-Q̣ Ó2ôï¿¿ẲĂ endstream endobj 292 0 obj << /Length 2044 /Filter /FlateDecode >> stream xÚƯY[oÛF~÷¯ ̣DÖd®äLw[ M7ÅbÓµ¾¸Æ‚–(‰[‰TI*÷×ï9s¡H‰¶«$ }°=7ë7çœ9¦Ñ2¢ÑÅơ¿¿>{ùVêˆS’$\E׋(Mˆ*J#‚›èzƯįWÙ¶ÍëÉ”+ËÉíơOg”Đ(üÔ˨?½¼đD%IuÊ(¦̉Í„£w™7Ơz×UÙ8ƠÂư}]?4m¶^WË:Û®™[½¨'LÇƠnÛ8Ö^xË„I"dÂ=•KÏDö$n¦ŒR¿Ư•ól“—ÀƯ1ư¡ÚdEyÈQшQb¨ j’Z:†ÿÈ[<ự­ÑưC,%§îĐ•;2¤£á„ 'îr qæ₫̀M’ÈxYƒ9Èd*¤‰_¹ƒC à̀5˜°¸tÓ¢̉]WM>÷ăªœH˜0çøë£û¤Â¬Q”ËDË7¨BÍÓhÊQÊi¼ZçÛ:oP²¶˜påùx×/*«v•»Áûú®h÷À3©âD«ô›̣Ä„EéÈutˬƯƠÁƠÙ ¡èú¿ùn¶.æEæ§Í6›åÄiÊFOœª̉_‘ëU^£ü)Ç dÜ̃OPô«ëeUíjÓ¸M§7l̀²ơl·ÓXăÂÂbàÈÔ;̉^ØUœED_[® aT}|ơó È ƒ‡Æ¬#\”î8IƒáK/ø®É=7ç,ój“·ơƒ3{3´@VÎë|]à÷BjkN\[e³:âÜ̉Å€mжŸîÖ¹YóàÜ!~eë·̉0«Ưâ¶®æ»Yë&¿RE ^›&4ÙŸ‡{´±~Å3›¬­‹n\ØË—º¯–·ÜŸ9¸¤h€,³cèt·WÁ©Úƒ ï袜çÛï!đ‡!@'N‚P8¾C»íZç„y•7ËúÁÆêߨ’ñ÷E~—×wÙl5¦” Í9jaâûUa­0o$üJ)¯›6L}áP̀^ ÜF‡i7 ¢4nê\ˆÇđB×€ÇN#®:‘ü¸&JO£¯†/Ûª°…ûyRø0R»‹p»×]±.₫ R*&î6`æ`Ä(27„º9>5w¸¬qåA}…Q£Ë^ƒṬ\₫4éa¢YÈŸ^ H<ư h‡áJÉ< DBÏ:Z<úñ„rb$ Ôn>VKăÛ‹1ÖB@́ïRœÅGˆ9)1)ơABg½S´Úæu†±7|rÛ÷¨6ä`|™CG””Í7£Q.% èxÙ˜è)Qi'ÓÏƠúa“ư–¿¿ûO>›SE 3vyÿÀ†LÆx }1F†2í'~ÁS¤c‚r(mD§Ë«Å¢(s[.¡#Á¹Û÷åe±\JÍÀAœwŒ0R l äëÜøáY3'¯»§³¶̣ lı(Á½A.\û\æ6{UŸ8†Pn”g*…"‚$c ½B™.µbƒs—¢¬H8e·́„IF¨T"©&fs̀>B»LđvÅkéWzæ„Ơ`NüÄ ]´nk¾è§$WAj|\3Ÿ§§¦²é{,,îaÑWª¡:­ëP6¾¢eMkóÂÙ›ë³ßÏ€`đœă1SÑlsvsK£9́A6%êê{{r×-ÄÂutuö/ÿ6L#CLƠ® A Db‰1€ ûÍÇl³…úሳàE¡ÿÖñS+>„]0Ø4h j̉C °‚Lö$‚“4åOSpU…'±Ïê È̉<.\^ŒÙE âê„åm¼̀¶ßùz¿Ô ưW“(ÀÚb₫Í·¶˜LY=Àœ,˱: +Ù¯)&IÂÓ¿|€9Ù&GfµÏ­¾JàƠ¤%úq0œÎrDê„PóYƠgđU)3è§)HÉ ·Í¾íƯ›@,Gäûÿœξö×éßôezªyĂ v́=œ{Í›;Jl»ñv´2x¼>ÖÉđPÿGœ ÆÅ°ñȵ±ÿê0´÷êĂÅg^ñŒM®{ŸR5hÉôÙơÚ·vÙvGá¥íCá™6Ư)¼fûÖ;r\Tơæ‡ØZ·JXÜäíª̣’uÍ”ÆÍñÙ́ÚR[8<̉6€ĂªkûàØ÷jaTçÍƯc'í#o} 1B°'m ƠV¯ß"Á7ïăÄRHJƯY¼cä W̃ï xeåålvÛíºÈçÖX¡…ëî?u¶ô‹û¾>Lº¾>ŒY×_À^£&Ï—{ˆ"Ѷ=­µ/×™œ ñ?&3º endstream endobj 303 0 obj << /Length 2606 /Filter /FlateDecode >> stream xÚÅZ[oÛÈ~÷¯Đ Fs¿x7²Ûµ›bÛM£}đú–F‰ôRTÿû¹PMI1® Càpn<ßw®c÷æ=Ü»¾øéæb|%tO!£0éỪzT ÄUOI‚ á½›iï¶ÿ·w&ÅÓºÜƯü¦ăÁÈ`æ3˜$°›ŸJ¤›tă₫ă+Íwg8#ˆÙ1´aÑu‘¬̉$ûmöî‹-’¹ư4 ưI²LE>ƯLÊ«"_]¥YZÚ$e‘~½†ñ"ß<́•G ¤(«äù $B¸~Bđ^1ïƠ;>^_Àl€‚H @Ø‚¸Œ$¥ư÷å„çưt®Y;J».í4΂l‹]á%H°­psÀ½ƒBRmgÁƒ`£#CMoDÜ„ÁơÓje“É`D¹é'Ù44̣uZ¦*ú_DômèÚß1¦HĂö`Ü€ă×/×yhyX®` ă¼Ý\Ä‚†jÛÛ(ĂưÓ^Ú…ü&  ªwHdK °™øäM6µE ‰IXVW£)È+0đ’ú5Đœ{̣Í|¿º4Ø*V•×û¤”ÈTă(<_DTxz4ï›đp̃¿·‹d@Aü4ß¡+Ÿ…k¹đ…èÏ6Ù¤Ló,ô‡^¸f@-ÛØlâÙu›=U+ăîùƒ_æ…¬{Œ"F^q™Ù?n…]/̣åt(ÅƠü׈QöŒ"YÎó"-«p :ÙŒ"÷œ#¦Dûe&s1í'`/_ÓUR‚ƒ°±»̀ă°»ÇÀ4YÙ¬L–¡¯’4 ƒ6ô É®…/ŸÂ„d:M³yœH7É<Á®5¬å&çE|`öR.·ÔAÁu ụ̀ia§E9G jûàâ)tÅ»̉ºë×ĐÔG·±Áơy´pơ¾2 ă™ßï1.ªK͈îÿga³03Y.ëK']è‰ÆUù;L¾·aëO€́|¤"/öÁ ¶,e›Ơ½-BÛ›¨ëÛÊh¼Œ Â­˜¡3Y6™>…›Y¾ñèŒ#Ë12±v'nŸy¹±ÛGí3_#‘̉êDó…1̀½mZƠ^¯‚¸¤H‘h#ªä¸{ƠOØôNà }ê¦uô™ÚÙm²Y–a—Y ¾’@Đ߉wß)!ÖĂ#lN1ö˜₫Ç|3_xŸ€îơƒM>g¼y. ́lkn~`̣‹¬…®r+ ›₫Ê&̃g¡¹^¤³H Ü=:ŒyñÙqû3È×û0(*$ß íø\%Ÿí>x\CUA«™à2~aµíRb[y\¿û°¿>Axל´I„° ÎÍ́‹¾ƒp•6´@»ËØœÁøº"$Û]ôG‚¿°#Đº«!ö²b~'ág•ÇtĂ¢üÅẴû,]¥.jnÆù7“ )¼Ífï³Y~¬îga„ŸVf‘CeVÖùƠ:4i¸øx ‚;•øJ$¸‘ï³ÉdfíDq l9—‹zơdeL7›1¶bLÖă¢‹0σƠsܰR¾ˆÔa¯¤ ­z̀v³]zp#÷ñ~7r»₫é¦đnW“©?u‰öDø-¡êñ× &¶\CG0lh́¤%\KK±'^!BøyY°IE«—@ÿ̀K̉s€Z±k· €ÛÉ"Ïסb /³ôT…@RæqI^L=(·™—ƯïêKYh=ÂæÏ«k \µ±?3]÷ ·1£ÁªN´¸Ùé÷bBçyºøåæâ ¿`;Ï=A98¹êMV·w¸7…1Đ!bà÷~æ â…BB¹uË̃§‹…3Ù ˜.„o~0¬6cˆq~ù¬–¶ù\G"Í)® ¯¼đ•c{àEF›Æ‚hà|Ï•X#¡æè: ØfØb'DÁ¶ơ˜¯÷Pl`GíĦ v<È$oc t˪Mü~»>„‹Èø̣ÍííÀ·É0\ñk¯árooë£#̉z›ÑûUÀ®ÙĐVy­©ohC­g`₫y´‡Ưœ¢ZèJÊ_2^]ÉwéíƠ»u©¶öœ7Ơ¦¡6á́·+]§Ü7c§M¢&:QDk›€£açr É‘¢§éáîGâĐÖs“6n J;—ư ”<=Û“çlz¾ưF¨9K¢oO{Ss ®ô\Ï1ÉMk‹çê9̣tY  KgQ_kî›ê£Q©Î¤>ª‘®ẾƠ÷êLÿ]êûvưĐ…úZsßTU¡gR‘Hóçªò¶‘pÛ́4Ç·f¬I:&ˆ‰sù æÈđ|†I¾›ßpƒ3¦ âøL†ÊŒûÏ‚>5Á—E’­/ßüº€°.ƯÿD¯Ư;F×p?2¤C6äC1ôjơ^y8½í‚íöT5ÙV q~& …¬ư9N(Åû7ëđÏß²é|á(ơ üÛNJÿÏvüÁ«íFü?¨oÉWwĂyÅ¿ûuWÔ¶§°©)7ç²yiV'Ûü§Ë7ïf3÷6üÙ½,đ&tâ]àçÜ e“¤´™×—ëô®2¼MÜ&äîY]è 5M†“-¶8̀°PˆĐhç?®ü,!1Å/\ó1-¡¥ă˜ œ Xóúmó·[°­%m‚åx%g28.‘§œ-Ư«©_=9_́̉YÓ!íÎŒZÓ̉d–äàŸ‡YÆ%́Tf¯ªÏ.³Ẹ́¯₫£‹ŸR{o‹ûd²¸.\LgŸ.k/¨/ƯĐ‚»£¾5oMêƯ uE:ñ`J…:Æû—÷(蹌U&æcø…›Ù%G|µµLMXX Eº LØ †é X™}ŒÀ(&G ´–£Å}p d'¢F!ÆiÈH2†_¥!¡Ăj/SÔ5‹N`iëiè’Öb4‘@m »¢ấ ÎÆ k¥ iÀj+Säcmº% âú°~=¤µM$J ï7H¸N˜±ÏúáG`µ•©‰ ̉˜éÈ́Xxc}P?Gbu{1H(…N'@¨@’̉£2©ÔĂØTmEj‚"î3¹n¬0$%9Í}Z‹Ñ@BŒF„˜N`‚>¨&ÇBoƠsU{‘¨´„úºưmüv‡ôs$û´—¢ DqDq'ê!p(W&¾yüqû1‘ßÿן%&å‘CV{Yp$…"̣Lߥ8k₫< àîÎí‰kr/0¢¦S‚ă¶®¾ù³@{™°˜†ª·“Cà¬kØáH̀”díÅh"¡ÄĐ ££Q‡$™Ă¯R?rÂi/SáPöv£ êÈY5µÖb4‘`¸êFAX"\½Fß›+‰f¯J–­eªâLuư% endstream endobj 308 0 obj << /Length 2780 /Filter /FlateDecode >> stream xÚíZ[oă¸~ϯ0¶/2`sER$¥lgÙƯIEÑ™N̉¾̀ ŦmueÉ+É“I}Ï!©›-;qÆH_ ER<?Ú-G₫èúâ§»‹ï¯D8R$R>Ư-FL ¨‘’”D4ƯÍGŸ¼¿¼ư0+ËjüùîW˜î¨O"?²ó9#\RXÍL¥ ']ønưww\à |kÅÅH1FÉF³ơŧÏ₫hc¿|£pô`f®q6b”n/₫n¹¦"I&‘jóCX‘Iâ‘%ư§›ñ”úÂ÷2ưp9 &<ß0ÓcBĐˆ€¾€‹}A@ ÂWg„Ä‚ẠmeåÈö™dúmœ&U¢Ë#¢̀×h2‚¥ÄyöÈg„r·G̃äéă:₫];¹îÿ -êͪ‹s:/â"$?¾#Qí­Đrñâ%€ á˜à28¶B0Â|í®RC'C­Ö‹IA°c´J¸ơ; ¹ÿb9ê¾~¼¾}»̣}ïj›ÍăµÎª8ư%_ÇIvUŒièåëké"N?Œ_’Uo³ùûâ>©>Œ©ïÅEu­óµ®dÖṣăD¿¿T7`ø£)ƒ7êx'6¨„AwmÖ1eƯ1ơ®–Û§†K˜àư üÈRê’àĐöAµÆ— X$U^‹ ±pĐf:,K›hØÏ@’ˆ³Î$¸Xåózz£2»«íêSA$£)å`mÎY>êj #¼¬¼ ½"´• âZ¡ØüÁù̃{đºÙ`0Ÿ€(Y6„ưên•”ă)¤o[jÓ’^œÙ8­t‘ÅU2g₫‚¬êz`™IµZÛ×û¸Ôsûiî>]6¦d^gyV&sØÎ*Oy(½›Ê&l–W 's7Ts’!ơGGca;«•F)AÜƠ×î*Y®m/—TµÎ¦CjḌfFª[áSà[PÏn:J!)ó₫ª«A PÀ"MÅJ÷Ú.Û‡%9«̣ßÁ?³ù Å ‹gêxŸ‡iJ´Ödh”ÛJ÷›ï³Y˜>Ú₫<,6Acé˜Ú€ăÙjŸ¨}ÛaHalˆEªHôi]Èz „]ØÍ ¨‚¸ºă;È¿Ï÷–E¾ƯØ `¤¶ó ̀óA›P>¡,:j!˜˜hµ °̀³8µ‹o0FíÇQ‚Å—‹Ç$[ÚE£^\ àk|Û̀ic„2F8èÏÎq›ËUßb#Ÿ¶³̃ R£„Ñp‡dŒ5È<j`₫6`4:)Æ@đ`V6â/»Ùæ‚’`¨¿@Â]$àÚVf{\(À¾Üö̀ât¶MăJ7Smÿ/ Z¥º²ưs›J̀µ́-t¹ÁàhºaŃ©C5VIÂÖå0ù¢¤@$NKÇë&Ö¼øƯ ,Đ— Ön§N3¿DÔ×LǦx–1«̉¶ we›q¡mĂÆNhü”è{]ÜdẓäïVn5̉!‰ ûU‘­{®bÇÙx®b¬)#…Í úv€À÷IüüZ[@©„É-́ꢄíJLV±ñÅ.^OYlS·¼‹BF?v»»ó¶Y=8Û̃ëZwùö@Le œO*¤ñÜÄéc( bZGS²_»’OđÀ”—GêGƠ ÿPQÎd.Íb4b–¹w_ăơ&Ơû”9£„Êè%¤÷jpÁ) !ˆ|C ₫ KÔL@vyÂY¢­f,Û+o±ăăơá“`œÜƠ¹Ëxó£+Ññ»^½Üí°e:®/ßÜn♾Æz7¦ >‰0₫đĂN¹ˆ¹Áƒx£Ï“µ±¯P_A¨£¯¤PX(Pê¥ ưrùæ“??Tèçóhđdñ÷4À±0ậGí ˆ`Ω?9d²ó´Ï‡ÏÛ§3´/S‰?|£B<̣ÅFảÂå›÷4o›,t“ư’ÂÏØ)á}ö úàơä‹)fđS­ÎbJ'ël_량³X’‚3í[̉59:‹~ÏjĂ{̉₫Nc_ô®^É₫$'R¼Ø₫óË7à@Kêc2á0ÑåÀ₫A³ü21¶l̉ĂY ̣T%îoo”Ç Áß”Ï^"Î˾8\B5ôJV· äK­ª†z üªỲ'ßưí_ÿ|÷ñîæçw·ßÏFNUɾRY` ÏsØSDaí: ˜ÂÉ$¸Æ£²ü–bö–p\Á§ê<€2”- œ(ß”{í­ƒSl kñåíæUqă=®ÆÔÛc̀ƠƠç< †BP£ƒ‰¯‡¨ƒË-ˆu"¦‡ÿ„WÅV×§aw>6È~Z: ÔMï‘°¸—̉«tY™¦̣’…íD¥$,Ç`ç](́¼PσWPkû½µåÀ0´h·Úö×ø¶ ®‚³,&‰_5Çđ̀ớA…9 * v c á Z $Ơàơ“8I’5؇í¦äÅÔ È,v77Qr”¹Æ>àÍí“̀Á8#P̉‡$[^‚ \zWIQVG%éƯOjœ› ûlÁux±NQi|~µ€u¹Ṇ̃É]•Dª°z8·‡ "µÄ\ ’€ˆ(Ÿ"9 ó(è¡Jè‰hƠ,BXÈà5adq›¨ 1‹K=2ú0 ~#Æ¢v©=”ôQ!X´@/Îô¼ÆHYäƯêYÍqË€‹7¯sƠP<Ú.ëÀ3ƒjẦƒ;–Oá3ö"RMljdNÖ1Âün}ÓÛÇ<1~´Đ…Î-C»„dâï8Eï-ÈÖ/mS§zmWëC™ÎV»X&úï×aá4ƠÆâƒ̣rRÚÅi÷›C¬A»¼C¬iêù° pÖ¨l‡ˆ ÂÔ0X›€Ëkư |…æJ”ë°6K‹oË̉-ü)ghsk»ĂÔ±ôŒ#÷ùIéù©́,‹}ỚÜ3˜ÉnZÈÖIÚIÖÑY’µ<5Y«ÿ'ëN²v¡,s]É^é„·¤¹)Êæ̃bQh]‡4HCº[è,Vd¿Dp¹́ÆÅbTÊÁß3pÂdđŒX…Q+`8¹DDƠQ5â…™`½ܵÀ´a5­C÷Ø`wa<'…I¾K*vDºv‡Í% æÅp˜ASnsÉơsîûà(yd8›;Œ‰aß<ơ%¡ Ía¥güAl·²&.§Ä?§x‘²ç̉°l¸đ -ĂƯr,> stream xÚƠksÛ¸ñ»…æ>Ñ3‚' ^§I.±ï:™ËƠñ´3uü–h‰=YTI*9ÿûîâÁ— »¹öƒ -ö½ ,èd9¡“˳7×g¯.”$$M(›\ßOx¢ˆL&ÌHÊääz1¹‰~|ư˼z¬›óÛë¿Âr:a”¤4µë'"fÍ,eQÿƠ…Ô&‰1ÇƠ3)ái<™ Et¬́Ÿ$áö_„Nü¯ZNúŸW—g“›£”Fç\EÙ4(µæ‰_¾È¬yÜæSÜ"ê<í•ÁŸ%‰ïí´¨÷6p a›Úvå|g¸ç% G„癈räÓoÛ¼*:>‹ßÚđiÆ)%2åCÉ¡­I)9´'°…Æ̣:`²`ưJqo#)É[[%́kíä̉YÔeuÎtÚ1Øø8<J26]øb¢EBJb»^({˜€Ñd´h Q5!c¢bía\̃€Î(–DŸoC j&ưb4öVUz–3븷>äͪ\øơ#Qtàg" à7üṸ*T›Mư}H1eB˜l ÈBhƒ-%­g_µ¥™’$aé‹÷yäØ)­á]†à±”]~ÉXcR¡—€68b3aü›\è5?#ùùÆÿ±v“Ù&è9PmZÏñú₫¾Øä? ×6đ”bsU,WÁ`Ç$(¿j]†›Ñ3Éc"ƠÈB?!‚^¤I'0Ô.CĐb̀¹R Û3\¹¡ø…o‹ª˜¯ÖÀ|ûí=²ùøR4+ÓƠ¶ÏM4emA5ÑI«*‡ñm……Ä@ô±%_¸]Ñ#À~ˆ}qAƯúÎ₫¢‹,o‘Bß]8W±‡Œ‰è Üñ“<82æÓgnÎd ªN¢‹ª|c—Ü3ª¤pü3£¡8Ö³³Ú®å}·í±(ÅA>é¤UŒ Èw\¦ó”EoJdYơø.qpæÉ¯ås t2M: "L!Ç‹,…T’¶ÍÂSt1<%6§c-ÈV0ưt4©ësPÿSóúcƯ”í ÜÑÔÙØ²*–&[R´ưç®Î&t½»>û÷:aزo¢„6 pUj28»¹¥“̀ÃRO¾˜•à<½ó^O>ưÍ&ô¿CÄFDÿ*bŒ m1÷[ö°]çû;CªKXœ~ÍÖôƒ>% àrp’êt‚bdÏÂ!!SMH–B°éÑS(;Ô0¸º 09ˆĐ¥ w‰ăñ2Û₫Å©,₫oÚôl²¤@q®¾ÿ³µđ@Ñ8ẹY L}Ü‚;hGÄ4EƠÆßŸÆ&r€oÑ{ŸÎ±}¦ƒ«Ó"9ÄA–Jh%cOrn†‡l×9Uđ́a¿62*Ü2“:DY•ÍȬkđ¢ûßR2êûÔĂAê/A}¢‰ŒBQK9ia§Sƒ̣#“¶¼yóó?₫iÅpbj[~¨µơèØ#GXs2]û¬‰ÁX—`M N̉§ÿ?—N̉å¦A1›£+¬0†Ăáº)·v$ûœë́n£ôd4÷)U4’¯cV‹Æ3`x4DJ(‹¿û“Ç₫ xºû{¦‰{C æ`‘¸¾Ås0̃³àøƠ˺¹“9³Ï\<ƯÄ/cè‚’& ën¬¦²éІ}ë,ơöˆ₫ŒØ>m ’!ú­đS₫‡ÄÍé {ÅqvJ§ôöåÔëd₫í‹€BƦ^D»(BL¾]=ó=ÚE yhú"Ä‹T’Dóÿz:]û¬„ËáŒææZô¿BOÆrŸÎ8!\«gEĐçÀđh(ç§oă…̉$…˜ô@Of̀>k¥€ẳ˹Œaˆ âǵă¥7ÔäÉôt̀Ä!fñsN¿ÏánÓGO3˜´qªF7ƒ€‡qª»ƯWUíº[¬ĐÖQ¸c…·»µƒ5΀¬-₫lËơ£«àU5@Û†€#e¿S*`\­Ä7,è8é®íæe…ơÔ„»«d́å [‰S¤5Û{F²Êê:m#À@̉½;ô‘ˆ4IÚ{v’¯›:‰ơ¯ă«|[å5 h —€lf›mV5¶gª w—rбHî¢È–Uö€̀U’ [sCS±s]–¿b%ÂỤ̈a8t÷|÷î2ĐÖ)°›¯s¼Ư¶ơ; r±'•OX§‚V₫ËCW¼‹¬_BáZêµÚJ5ùÂñ^ ö4>PA₫p¤*Û'J÷µ´YeƯ°¨ñ4oT3JZ:ëÂÛYÉDt9,êXRB¥•ÙT J ¿€ơ=d¿æî₫…S5ƒœ@÷Í5xmÖ©éH·l ›aQ¼W‚1“f†Å!–ư®\yJdW»CFBBn«̃ú́Çx“\‹×)hï Üik£kw¡±\§‡ºÙ”xĩ«ñàǵ̃/ ‘çŒÚ÷øµöï1đ£ ß³3g£®NzP‚hÖ2‰ K¥®*ƒÀ[j,!Jhy}ŒPơ„0†€Ó5¨s₫ĐbfÚV®YÓÓºÚÁ9 >.5DUߨ†ƒâkUhd¹¶À<`yYƯMm‘/\;_•€'r!æ½§*0“ÛG*Đ Sƒ\P̉ñ VƯùÊË~cª‹f§¶påv»öÿ\₫Đ¨î †ˆw)Ođ׺ơfxĐKq$…P'ă!Z¿ékH R5₫$É’AƠƯcœº4®`S4ĂM>ôFø̀È6 w½̉µ¯óÔMµ›C …ƒ¶Tãäî¥̉!–r̀ăøIÑ´{xâqÎ\‹o‹́Ă"ñ»zØ̀¤ïµ̀đå?s|â\êf3E-qÖ¹ ² Ç•¸µƒ"¨àPÄQP$î^˜4™iÆ£í¶z2ཱིå>‡Ú²åDƠÉ!D ^™¥lD ¤®ƒ T³ç( —Ó´u¸̀nºđÇ0%:Ë«6£ 2n~ª£ ZR Y’v‚VÇưÎø•ˆ[W‰+j'¢ă1ê/Nà“1œÈl³ÍÊN˜k%A¯Ă18] |ó9¯0rÔSăŸđqNơx̀7hBà× Œ'Ú ßqˆCøÎ¬Ÿp:`ăLn™WaÁ­‰C`P‰©9 ³äp¡ ;V%‰JeÚÎAɧ$î^'}YFz°QV¹ơqÁ§¹Í±̉ º`i=@æëLƠE©“Av•ovyå^°)X½€ÖF'Û¯w tc¨´>đ‡% Éî1N”6œ“º¸Øxȹí8aëdÈt·$`èxD²—vZ¸£sZØ5×á©OĐè°«Çæ̣ “>‘ÅHe”ßư ¼»º₫é‡w¿ëƯâøcrwWóózP endstream endobj 333 0 obj << /Length 2715 /Filter /FlateDecode >> stream xÚƠ[mÛ6₫¾¿BÈ}Ñ» _E2×hîºÛ‚ôn³ÀṂAk˶ZỴÉr̉ư÷7|‘,YZ'̣ F $MIĂ™‡‡Ă-–n/^ß_¼¼*HKL‚ûE@¥@\2"HÜσáÏ?₫{V>n«ËO÷ÿ‚Çq@0̉X»çE," Í>J´yè{ùơ5¸æ„!ª£à ¤"á₫H©è<|¸‡÷«ạ̈ fi=ªâíQ¹@„Fơ Å.ŸÇåă~\"%ơÊdS&Û$¯¶N~UÔˆ€_",·á¥M2«̉K*ÂÏ—D„¾qIpÏtyÍ( ßT®;Ư:9qË Ûªoâ´ÜvÇJó*1’— Ü0ùZ1$)®HÁµ³çĂoWËOƒÓ¢Q @F½VJÂÓK–V-ø €XÓ)]“­ë|uÂêK’än‚;# )U=ˆÄî9­Ú)`S£G>¤*LĐơq>’BÀq\ ĐVˆú‰+cB~Y%e2$qDÅ·keçÀ©jóƯú!)]§@¸Ö\đđƠƯótäÛ´ÈítCÏtiĐ•àÜƠWƒÚ¬BdE‡#$E—2÷+kͬC³³.4·Ä…îÚ$÷ËZ×ă)´f_³HRư5‹ Iä̃$7öG,pQºvÚh;Ÿ§kÓÜÎ/9ö=åÖwÆ̃öؽ¹.æ»̀ßZ&yRÆUQÂ5€c¤´_t¢Đ.~n“Ytµm‡åÀ²•†HÍ́-‡ Uà@y‡j¢¦46ÅŒ°í/ç-Z·×qU¦¸vi@ Ùù̃$Yµư—á€í@S  q¶çḾUä̃ùÁ½Y±̃@÷ƒÅú¿¤ƠÊƯqÊ?ñºµî-ÊÄ/]`pGM‚8iôüuˆ„QÙPđö r Ö¬;G¯w"¸í^0’QĂÙŸăÍ „Emû2o¯Ăø–T«bî e¤»:“­#³̀¬L©ÂYœÍvYl\±Uºbw±AKƯ©ÈvB¸úU'ºK“€7hlX–ÅnØ 8×í½CĂÖ¶pc¹¹ƒA>›ơg;¯C=æû)"Q3ọEq,–EŔư‚À.8@8pÿ…àA¹ ºw&l—Ç9ˆ%Œâ´µjRPé~®‹2¹̣Ó!8°LÚKƯ9–"3 Æ¢(׬̀øFˆ*wÏcúê½Át2›kko0¤¹ëNö>ËxbÓ5+÷ze‚ Q &‚Á”Ö ¶3/“p—Zn¾Ál:¢Đz2YĂ%¶÷ˆĐö1™»§]7Px[¿WÛuå©i)/Ù^rÖ¸×ÓÊ÷ÅïuËƯñ¯’ƒw­q®9_»¾2«ëk÷ Ó²ÙUÖ‰]ütñ¿ ³ÖlØÂÂĐv̀Ö>á`÷@2bàG¾Ø'×Ñ :fÁû‹ÿ¸XBct±§•5b,a 1ˆr¬>?ư¯7Ỷ™Q‹AŸ2tG}iƠ‡U£Ä18 đˆîIK N#¢V̀Ḉ¸ÇXMNBkƯ‚ÔîB†»ÛŒAK¦@[Î’xˆ—ñæï̀{µ+°Ưqç°†̃'•q>oX$üœdÆ·´½Ñ5®âï‡îæ -kÓ™̃×±¨ôq$ÂRœ Xătáüv"°·¯¾¿pk€5Æ Ë®H$¦t4}Dœ‰!âi¼„B{":ÓÙ¿ûó»t¹ª^¿~÷ß_íæebWîù+9¸rw±[UÏg4Œ6 ‡ ầ󰛃ÇɬZ̀_}cäƠµ‰³ë8Í_§ l¶¶º­ w;ÙF£ÔDñ4dƒĐ]jO¶ï6Eö¸Oa‡ß¬7›U?áÍh]úæ gåsñ"hÅO¦M´ùÖàWU:K~̀ç¯}j¸cú-ZÜỲ¯}¦áÏh´ú€c8¾èiøÁµR>˜ưÛ0 ‰1›¿TÆêWLø6ÿ6a~„P£•ëÙǵ@Œ³)́ăZ!8¦uÍ3[9/É}Ö<—n¶o¼r}ûDƒJMbŸ–‡óÇŒô%¡'8Z»¾Nàl ”az`ßÍ8«2·ˆƯy‘'Í^‰‡̀æ.scïüĂŸ)̉|é:ÚIâ' mWgg9ÍÜG áèpîàpwÉ¢°1ÙÚb€:bøh­û†s8±Đ38̀2ÁúÔmâ.™½‹×ÉÖ!‡ól²đa< }$™@"†BL#"üvúÁñâÅ*̃n“>ø|a’ÍeÄ—À˜®óÓڌִo,ep¬£g¢ •ˆh}ztl ¥4(@Óf4} áv$ä$„!Qî óK Y?œ,*תÓC6ưlª̉üâá›Üü¨S¿̣„²Ù Ó0|º6ùßkp_₫æ“Ú!áʽM¬wí¥ë“ñÛ#ÑíxËûàaÇ_ưœDÊ3Død”‘ÀKàœB /’QÊ[GmöÔ c̉Ô”›C(b<Å]–Ö'6€k¬3É7å%Qa±¾yïCènm÷¨Ä—7Z¶s»ØS&¬U^èU*l³Îÿ¶u±z\)Uếp?Ë-$!œó"3|#²îîj2û¬u&Mnz_'¡NfÚẹ›S{ ›”VƠ–éáƒÜ]RíJ“ơÍ·¯¨Y“}ÅïÆåfaóoåù]yÏ=בưf8÷¯‘"rÉ`IB1¥:u(V—À™)ÏrîÚ.»êÚĂS < Í\ÚSÙ₫D3¹?”µdƒåà8i— Ç”̀ O”@ù¦Ü|×Ⱦ^)a´—›8±kP¶]Eđùl€æC‚"ŸÛ¨ÔtYÑ&y®¢ºL½‹]>«Ë9ºä₫V<„6%F“­êÔ]‡*½B CTñN…G†¿,j-wåÖUEz¸W üöÏÚơv¹~m¾*p†7µ_}‘pî:ạ̀Ö½c~́. C—rs›̣7‹rØ!@Eª7™ƒuªÀ™«iÊT'ŔËăGîmfT Ä5}Îfö µ@.ÁäyB:*ÁR₫'Î^‡£hD`(:E€G#dSgÎ^7 x䈋Uüc©ü•²×ăQêÍ$ÀÉLA6Nêốơx]úæP$‰ÎÄ ³¿púz<\}Äa—9âÄ… 'g‚|”dưŸ?ftÏ s+»pƧ1&Háh’5¼ÇO\~‘.êănSCƠÊo îœúÇf+KØ2UI™n·G–ôhƠ{Ö‡1‰‡2§:›³µ̃ïx&Œtß ́·G›Úxîöh[G²°ăíêCc¾6Ô“Ă|,Æ•OÍ¿+üLye¦¹Iª¯L€‡¹ªØ<úœÏç8Íâ‡,9féh5û–B £O+³5Zœ.¢Vℯ~B3•«3y !é_ÉƠǧ1§ă¾¦y?.PDäÙ<ƯhÍû¶3<̣Ă—§g̀~™úçpt£íêCc₫ `’ăwó=ÏÔ~n¬–};qç5ñ> stream xÚ’MOĂ0 †ïù>n̉fœ4n!!ø̉Ä̃JÓU¥mÀ: ñïqÓ CÛ!rd;O^¿ AWê,WG—œCïHC₫ Æ1Z.Ơèµ…| Eïúôv²ühVư2I;&ôä»₫Ä`’j¡…VCm“¢È¿ÈƠ›j‹rF˜èg ÚÔÀd®’`*µ&>ƒ÷Đ9o»åzf˜ÁƒºS„’‹3Ë ~&îă"Û£OMÚệB̀äN“"Y߉«Æ¯'¼pnM Àï B1dĂ½›ºY=SAˆư¡îÙrp^ÏŸMư²hó³q¨ëvGôZ·zĂ:C¶ús6ư•×ar{ ₫vO[$AÑ–˜A9F£‘ºP7¶Ï¸·ÀÍÉ¡àv# zqü7áKÅáÁQD¢ư.‚µ ±́ăOo¿Ÿ`½\ endstream endobj 344 0 obj << /Length 2231 /Filter /FlateDecode >> stream xÚ­YƯsÛ8ï_áë“2S³ü)é̃r3MînfovzyÚld›µ±%Ÿ$·ëÿ₫‚Ô‡Cg̉m2¢AAà€á‹§_Ü¿ă₫û‡wï̉|!93FêÅĂv‘¦•^-˜’Åâa³xLno¤NG[oª?o–Rs |yø÷;Îø"üµO‹éÏÏ÷sʲ<È™/–iÁr¡ˆégÛ5ûS_5uG<«¾ÿ,ÄƯ+ùñNó…à¬àEà£K‰ËĂ®‚íËdÓ¬O[÷øK$ÚÔû3QÖM½¶mm74ñ­êw4Ñï,‘Z{lm,JÔ&›m˜›hëÔ4Ú²›ejṭŸ¦·cÙÓlu¡NƯø‰ˆGéÔÛùX¶nZ{±:pÏ ÔiÛ–‹̣íFđ¤iŸ‰|l›¡“¯Ơ†Nh’mư’®“?Nç_Öôµ¸çÏ̃Ö?qmÜ58¦́Kơç£ơ¬N‰Ñ̃°₫ö×u{‘ƒ•ơÆßíí¯Ç¶:XæV Ă •Í—̃µÍÖÊlE§t?údo„wE>u t[pWNLîiÉÜo`¨dX±²Ä·¤ÏSÛœº’€lºÛ&Ä àï7KÖw·Ađ¹<Š¿Ŵ†%<–ü2,ÉX‘q·"‡€Ñ`!fÀPnUf˜IÓÅdÙÈK¯É—)Vä&đùs>|\+{‹«Zë˜ÖÙu­¦é/,1Sÿ¥å¿ó ?*ÿ,q¿Å¢¡`\ë+Ñ0‚ưvX‰»TÚ0TØ…¬¦ÍÛÖÚ¨3ù¨ĂÂ?—“bPåĐlN{@™C ‹́ÑbhU“(Y&(Xü*‚£e&˜ÈÓ9î*•ؽÅô‚ø§RBI ṚÂ+z ¥yÔĂî5Å SZN_; =V^!‡9x† Ï0±©¶§[H .G”K 幃 £©÷øC~£<”CùŒ‹­_̀–d2a4K¥™ÛlRdIµ#â¶iẮ4­ac»ª-W{ÈË <æ®j» ?Eu,­ùVí÷4Ú7Í3J/î]@^¶›˜±ơ;×>àÀ¦NÆ®râX¶|¶Çh`qÀ½ 6jA”'eG_, ¤̀œ‘ñ÷Æ~JW—¸é¾”ùWÉí¶·-íÁÂó ^%wøziPíh[₫¢°A»诲P,‡zaP­ÂºFœ²$º‹2©/wLå4ER:]€T7ù˜Bi¦̀¢ư´ƒ6¿b¼Eäú—xpE V^Ÿî´ 7P̉~‡́¨4Œ{:s4$|ä9ăb/¬nƯ7ô…Âë„U×ÍáKVƠ¾êÏD¢"ƠÅŒ4†¢Z¤L¥Fúbl*„/‡o™xCe¾x\BVá„mÈư¿£™á8v{#̣d0‰4GѺ ¤Wbăj ¿ ›—Đ ä^ù;,F[‚n®ÄưÛc¨*&´ú¾Z& ª @QL3ª -Pû¨ßK¢¬ÊÎ…- ©¤…©útXY¯tƠûÙ, Vd‘&w§£ñ‡‰Å†̉Ån »ÏƠǃ6»̣Fro‘™Rˆ\Ø9Tå̃¡sDÈÓ¹¹€e ªÚ6xaÆÉ™áKÎ ƒPOæJúŒ@í¿H₫åyÛrƯWk8¹Ód₫TđƯ4µŸ[½[;-ê§™Ạ̈ ¼Ç àơ¨G'°­|Rçh¾®7¤¨™BIv™đFŕ`&¹×’)L˜Î^Ëơ25LfúMEJ¦¼ă?ÇÜ2ƒZX«ÊÖk7Ëñ¨YÖ$ûªë»(ôñ‚%;ö½÷Íå¦{MôÇê1Ê.‡ |ˆN° óÊ*!!̣Ë®r<‚©đè m3œ ưɶ.Ư¤irK3Đ₫áT̉F)$ËG©Ơ‡§/1Ư”`\åœđî´̃‘’ÁD\Cpöh*B# LáùÔ 8(ï)"úK=S¬Û5ÍGƠ¯˜¢`X³Œ²r¨R¶Ä.HÀ_Ï/ˆP C¹ÙT}5óđn“`j;O:₫’>̃<±ê#F —ö?´È勼L2Êè¥üơu½Pøë…ÛƯÆ¢@FSZ4FÍ́¾ê+·!Óï« %+Æîơeù@ºÔä`đ+€YWûµYưa×=M… BzO «}Í'yÆr.g˜Z;ä›f”°́J©/̣ûüĐ€àx¥î^b}̃ëà„®]¦ 'œiWUß–­/đ5Íơ\º‹.¼²æ¯(k÷B/t•Îu¦ºj̉5}‘Ư‚1M“₫~YÓuƠj&ÊætÜWë²·a[:M=đ‹̃DurÏè7ơh8ÙO^₫üœ¿j¼Ÿ¤ü÷₫Æé³P '¿"¼„`|@)°?¾=æÙđ² +€î7ỰÖÓË0ØêơđJûÇÁ"<&ĐRVëßăêZçÊX¢èI¥œ^Σˆbz*]÷B±›Ù `ôçđŒ‘2Û‹̣ˆ,?÷¹ûK#gù+ƯCúCó ΂ñ¶ ‡Ñ1dä’:og_¸z®u¡G'Æ®C—á]B…8BZ8` ¤søë ‡0Cʇ₫%ÆEBvÖ°«¡4 {|}Đùđú “đ Aoå^ö=^)ÈOY®æw¥¾}¦"8‚`P‰Đp…ô©§µ‡è®ĂyKS­ưß©jGß(#ëI7,ù¤æáñd²Û»́;TO;?ü¹³¬«n{‚ÿéƒÏ¢û’Z=æ×¡… J'…Á#O>í<[Ÿ¯Qp?v‡SÀܾütßTú‡º÷ó5÷63iÿ€"¾ &̀ÀakûS₫aÔ‡öơ·û¨7¦ĐØñ††¿¬Ÿç¶$üâ*₫Xù’f₫J¹½5ªëz7Í™Ê}O*ÅlÓ§‡wÿ#ÿ. endstream endobj 351 0 obj << /Length 2325 /Filter /FlateDecode >> stream xÚ½YKsܸ¾ûWLt¢*#, ææ¤¼ë¤’Ô–£›́5ÍpÍ!§ø°Jÿ~»ÑcŒ½+Wå Ñ|ưu7Ä7‡ ßụ̈æï÷o~úY›MΜ‹ÍưÓFæ¥ù&Ï+Dº¹ßo’÷oƯu/ưpûé₫_°œog/h½’LevsK¥ÄEo¸ß?ünîR¡˜,²Í̉̀dV”R¯Öÿô³I—»Læ*́ưØÍ¾́^>rÍ?oƒÓ(A°‹ÿh{{§¤HJøáỴ46»¡j|Ê“çcµ;̉°³Ă­HÆ®ééy8ZT§̣`éăª!q…YyJ ï?ÓÙ§†på`¹̣†¦U‚óÅ2Ų|̉û#ç|²n^“1QL‰›ÏŒgYíÓlRDÅYNb‹m©˜â:¬¼Ç:ëưr°íÊ¡íèÈ‹ˆ1ăÅw½¤c^Z+“2‘Ë¥} W!À$“7PL§½ûo;€’2Ó v9à(M{+tr¸ƠI9T·R'_đ9êƒÂÔ7}ƒ"Ă²ó̉¾à¾e]íIdÙÓtƠœÇ†4•&϶®8N§É?› jå_îÊ~RßÊư¾Z©í4Sîgºđ <¾œ¾ D+8î…¿Ü'_Ă,˜æÅŸĂ n·@>:óà‚"ÎîW')7ùæNJ¦Eö¦8¶§vhÏ)ªíáD÷5Â(“UÀ²(VLÁSà Rº§O<ĐÎ]¡‰¬`iñ:Pù5–øë«("e©QËB’2tØŒđ^صÍĐ•àˆæ@v¢gï?²€€ùW¯ß ¼DÑç)ơ«(‰rtfEq‰z<%̣W‰û¿8œnEæ#´È[Û“m|¢]<—àí̃ơ§¨0ɲÎWĐºÈ́U`ü.ߥZ$÷dQ˜pô’Åyà8ªĂq á£.¤aœOûTVu´‘…|¡Õ·(₫ÙÎ|Ù!Qn Á@à†|àƯØupơ è”K$ xƠÑ̀E"˜a©£·¦oO–FïË3­ôÑÓ|Ù÷cXă2QÄN©&â+‹z<’M©‚µh|®†cë’¶ưà£Wq u§°r`\L´JTüª¢íܵgÛ •íc†èŒ©\.jµL+´Cƒ²u'Œ” Μ˪ëc®3«¬ópÓ”'{³½ù‚¸»‰I‘±¹è¡ơ$‰2½ưĐ9îĂqÙ́éƯÓó'øq̣èQ/ˆ ṕƯn*sÀzlÛÚ– ÚÍM̉Œ§Ç€O7AÂc5@´€$’¼óh|‰bˆCÙ®¦,pü`û¶bÅbÁ„̉sÍ©y7WGƯ¾¶}OÚº#PP'CµçÎö"%î’*lă–¢Xæ¤0\‹¿9LÜJ¾ª¸Öh@óI/g<ÉÎY²QdüD…0L™–b8a)ÏçÍkÛ†ăÍÖưÂæÇøÆÆrÚøùh»¨ê Xp‚m- 4V«ØE¿¸ €?ÄV ]~]¢¥ÆWu8èævÏÓBÀÏ•êĂÍîXbf·„Yµ»ó·8w~™Îä*8Ô ÿ˜©̣›ƒ#@Ô)2Cplăœ5̃ ¼ox :sÿi¤&\S(–‹ ×4-FZđ+‰D¥ùœŸª¦âüª—Í3Wùœ†ÛOñßÓ³;’Bà‘ô~É‚öÜó®lhÍ£_€T •¯½c7M2eœ™è~€¢ă Zûpzâ|±i<–-ôï²;Ø_ºv\@éƒ=Ç‚^™b‚¬‚„f’Ù”‹Âf 0]3£₫)3₫r »v%B×£~|ŒÁ.E2ŸRÛ]´bÙLPkÓÖî.Gx̣w²†[ú==­?Á&C‰yí©Ưµ¥ |£á5®¾²a™Tp}I9os§!đ¹¹5¤‡¢Bü=àqxđbǨ‹ü_K«¨ïÁ܇E´¸ÉY&Í÷ă–3=SFå5óÁl‹¼‹Z•}NáÁ§™Æ+ưị̈b…ªjÔ±¥&÷û’Ï0 ¹}åœËc”êpOS(͈ä\—;Ç#\Ó%,¡{ú@<üĐ9 ù-œßñ³¨ăr`¢T¼’s‘l •$h Xy ë̉ẺÁĂDA‹‚Í₫Ê1¡9W,†Û'7xjë:8B’æ Ăÿ¶nU„ù‘£p5&§T‰×Á. D:m¶¹–)ñfG̀ ®µ×t¢—ÍX‘Nù1]̃"…Ë=˜.èÜơÊđKÓÀ…Đæ,eC£ơ eTC]zºº”ƒíaqè¡2pH«ĂZ^Ø}u-x¡Ô©\M½7:,^R03W¾ánXé²ï4àS™₫ȉΠ#ZÅ̉l¡ÇÛ â–Æ{́®ƒç̣L€̣Y¦̉æ:ø̉ Rƒ̉ê¿÷/ׄl@S=#û*ª!Ơñlu+É%œ³©ÜƒùΙ ÷Ír–Mót-¯¢HĐ¼.pú-‰Œ`ó˜Eù sÈÔéơÛí?r’yÊä|8ú Aøêü<Œ]¡@eû„ÔöÔBÏï8ï{dºsE>c²héa‘úé³X‘›w;{ÁoÑn§€“V^k‹eÍ<Ÿl̀)ËæîÉU xcw¶ï¹9£Z̉!Tk4|ÓƯ¸LÙp×,á(²‹›:H>¨˜…ÓÄ«®‹û±¬iHWs«CgÑÿU¾»ó;£c+ endstream endobj 356 0 obj << /Length 1816 /Filter /FlateDecode >> stream xÚÍXKoÛF¾ûWđHÑfŸänoI»)Z7p…æô@‹+‰E "×ÿ¾³¾d̉¶¤ÈÁÖ’\Îă›™o†‹ƒm€ƒ« ́ß®.^_rPŒ¢ˆ`µ â &‚HĨ Viđ9|³ "<t‘fÿ.–TàđíâŸƠoá ư;nƒáåÍ•—̀Q,cb$ă`É’„y¡ëµ®ª¬Ø:‰I‘ºÅI‘<©»G7º*ó¦ÎÊ¢rj½ơVáˆñˆz"u^Á[DaeđyI06JÇ‘¡®tQ'F™yùơ%!|¨ƒĐE‚‚.«cé6툕¤Ưñ¡HµA¤:oœß̃W]ïÊôÔ+‚‘Âʶ$Œ#ÅX°,%÷àåùbÉ8 ÷^‚½È³ªÖ©[ßê¼4a»s—ụuAp¨ƯUầiE„Gˆ²Îđ_“C¼Û?6,&¢Ư^t± "¼wGµ-–BFá‡7ig­!a «£ÛÆ`Û᪽́¥vpŸ2DydAB8­ërÙ·¹6€̉đ.«wfÅœtsklƒ»Wnlj=}5zÂàIƯ º}ß ¤ĨtêL̀¶['óº÷7åqïn¥ú ÆÔ‹‚7î­[ØùĂ}©Ơ»¬²°c„[́âÁ“zAB Ÿ¹:ÏƯ²;IgYâ.Ólc|Ùè£Ï̀S¯\̀ÆœAú+̀Û _½ù8•(̀T»Éâ2Ơ)¯t®×}8²ÊE˜ ÁÙ‘¦̉¾e“yË$Ô|W‘«ăưµ₫·v•ơ dÊHiÊ4j_«K§Ă†(m)Éÿy¶N|’á'f¿À‰[VMV÷›Æ`#s’`…”ÙÈÉ•§‚(¥:q«[½Ë¬%°öY¡,T₫NR·+ÿ*¨ḳÚ?·¿¦@gƒ²K°4Uª̀NB•́ưÊg-¬’êDMV€@HGÎxø¦50ñ$PU<ö-±5"Ơ $F®”>?áiƠÜN²«i c‡R ”úZ”ƒ´/&”(“Ơr’ùn ¾ôaJ«bÀø|Z­a%V΂»]¶̃¹e—î„ ø1>ĂŸá9Ë¥BLÎX>c6E²i³ª̀w§$7-ăÎüKîư=O€YÚfs$‹ù8âï]vïƯ;…öèa]ø‚jªº­¡Ă¡<Ö½Ëv±iuL¸t́;®„×› ¾¤„ ®úœ¤ 0 ƯlpÖtđWm™µ,¶ºªÿ^@Ñ Î —ÆỌ́ø»®kàäa[jVRñ0HĐ`&Sí¬„&+Ă.Û@‚…̃:oÙÂ2BgXk”!,?Ù`1"m(4Ú÷óQG$ áƯ½]Æã¹÷À&&U]QŒ¸j,Æ®^)‘lÂû–®ÉÄ„7˜…˜˜=ʶÓ¡MÂƠ/S ÏcD¸́µa{ëa uÏF̣.vÍ́û)€Åtœ"ŒdÄ_ÊMNdó„äXÁpŸU×¾¨ăI p'̃ñÎTÀÁwAº¾9ŒéX0ƒ~%:Á™‡&qÀt|àîz)ö‘)ÓÄ)ư0ƯƒÆêd‚4›™)do­cEîË´q\w@¨0 #đØH ŸëJÀ̀\Œ…×e­6Ût'¡TÀàÏÔ9Ăy·7iêrÙ°†.yï´8R‹ưÀ&ĂªÜ{ưs-> „|q‹ôÍH‚]xܦS¸Uö> stream xÚƯZ[oÛ6~ϯđ£ Ä,ï”öÖMÖaĂ"Xv{PbŦH†$7ơ¿ßáE%S¶²K3́!Iñr®ßw(/¶ ¼¸¾xssñêJD …b…Éâæ~A•@\-”$(&|q³Y|^₫đúư]u¨›Ơï7?Ât¼ Å8¶óELØÍL¥\OºÀnÿWW†x§íǛ©øGQ®¨X>.tFaO#ȰÍưíĂ^<#́»Xkơ½²ưÇ÷+ ªƠY+ñ7Ëü0Z̉Ê1™„C›‘!!H¤RØË$„dĂh¬‚ú(DE·ö>Ẹ́Đ kB9âF.1L¬mp̀Ÿ“=,"½¼º£³G?Möè†S̀½ z¤Œé¼ä I&Ú¹hµV˜-ßygƠ{(©¥ÓT?‹̉ tùz s¢èƒtÊAT"Ơ –Ơ™¶G<Œ¦Ê¸-Ưáă‚|.ü¼Ï›l—<|hêo ½íéd9Ø^M#ÀWóTËCè\C§â5ÂNèË ÁÎ  ®/zMK|E“êî6­:`³“‹ØKÛÛ¤»´ØdÅÖÍ/F´ÖvéIV£ÀT‘êäú=F’ªvFRl‹P¯̃!ˆTŒIDÚíƯưDäDDœ‘DÑ‘T£m4(Đ“R ·©4 W¶o =$Á9öUƯÀaIµ±£UºƒØ‡$Í̀ JJ¸“ˤn×wέuˆ¡œWØeU[ éÙZat×r¶éäu¯ H(ÄGƯUåf7£Đq¡ä“N“tcn£¥gƒ6L8̉‘ ñ‡Ø×3¬}nÀá‹ƠÉƯu埋8˜¾9œßFGÅGG17§_A £;X‚;*;>Œ=„9oaÑ‘‰Û̃¹vèKỆÜ'y]Ú±ÛÔøaƒ pUÈa´eä´UîÓàerXI±œKdê/™-lÓôÓơOiÓ¤ƠGƯÍŸà^„ß®*'đ›–ËÈd噦»…Æ“t—çmĂƠzDÏ^ ¥•T/Ăy¯mxXU¦/…ÎŒYªĂ‰SĐĐèßá–K»ËŸ8ˆ)¤úyO™¹úg´iÍ6MÂƠ Ü5TiÛ0¤ îƒ…Ù´ĂøÁ©ànPø‚aƠ¡ÓÑ‘PmR6ûú鉗¹ó²ö*N\ éĐ́=­Q %,T¶œœ3é́ưÔv÷¦´O4đL4†°xTÿ˜L€¢XÍsx_L `Ïß%™;ØĐ&VdBăÙIQ c<ó \08j@LÆQJXLU>đC§~%æy‡1Ĥ˜a"¸Fr÷*AÏøºĂ¯»Äi` ́kd÷eơh[wåă´¸ÍƯD—“Đj’&¤®³†C“0›â$W£xÁ =w:´L¥6œ'ÆT¦}—Ôéåè½G¬Đû¢i;ÉÛoWO¡åøZ‰₫öâ×LÇ̣hË–ÑßbË+c¾ÍŒ/?‚GÉr3-‡h“lùêäJÀR‚Ơ¹OE íÑëEÈ̉ÔR Í<º„|wÉK?8S¸6tĐưÔM}ºôŒâ!]Îh¿ûÀØiºŒüú>ˆúƧW³m)’¼=Wô„)ŸDc"‘ I0 ’„ÍúHcî@̃=z³ ™¸²sfñ1ơö°ôSă)c‘aL6fL=0‰ß)²¿˜œđ¸ècúxÛͳº±-s/u ZÛ9í?ÔWb5ÉŸ́áx@‰gëÁƠ Î‘ÊÂ?<{ú„NKŸĐœGŸÚçí%å3ÈSÊsƠbDÈ>ARCŸ¾Föá Zú„¾£Oh9úlƠl];Æä £êÏcWï»ÓÿœHăgé›r¯O:ür?¾x~S̉ôÅ0"€cÓd ZK¡&ÉÖ>:²ô‹Ä‘ î˜cL(· }¡_ïÁ6 >]Ès:Dëä1}₫̣̉ Đ"1GL͹n ¿´n q¨i”ß'ùƯ2Fó8Wî;nÜ:ë7¨:xíN7/µ½̉úm;=O‹­FƯ&½÷>+±q¨Œx“¾LÁŸf(Ü;Ôñ₫[aËÍ>O;Ưƒ´Á"7)5₫-å9?1YºÇHÆÑ€~nLÅÁ˜‡Uºça•î/¸ŒZZd^ÜéåÁiëI‘èÙ¡7Ï0‡æY•º<'–{ ê¶-« ¼‘:¡m=ă"J7lNX¥G·ơơwCxnf !„ºçÛ›‹?pl›Æ endstream endobj 284 0 obj << /Type /ObjStm /N 100 /First 871 /Length 1608 /Filter /FlateDecode >> stream xÚÍYK7 ¾ûWèØ^d‰/IÀ"@ض@ Im9l£X4°ƒ}é¿ïÇY7ñ¬ÇÅăCÆH3Ÿ(’úDR2•R Rƒ-ÔHZÈLj ¹h "7ôs Ă{Í“¡O¥‚găU 1V}¼†Bßr¨oZÂL%4ˆ &¡5 hæÄƒvN•Ѱ3Ù‚ZA£@b«!S†† ª‘4 'W„BÖŸ†prµ)¡!!Ws ¦hèqÂÈDºà„ù2•ÀÙmĂœ¡eFûŒ SøÄ,Œà3X/ 0¦!ƒTNøT”œƯ1É₫–¼Q½ƒ)~̣y¢X¡AĂ6&tDđîb™đSöA£E ¢̀eai¸4ăM„¦ É ƒ%%7û:2ÍçÉŸ0ˆâÁÍ̀›,ŒÅÁj»±R•‚[›ë1 # ˆ†5‚’A“+ ­5¹u§7°ƒ§VđtiÊh4È¢‚ÙPK₫ ˜‚%,đJq+丼Óê† ZÁR6Èo”pn-¸!­,aZÆ[K ›ËâàM®.P~đ!¬²Bi—ƒÉMS]0ˆlêr ªË)n.ú˜¹œbÁ ÜËĐÉS¿8Ư³ƒ!¹BMÆ&°– \]>Û|®¿6Wɱ¶·˜ị́"LƯufµgê=S‹ÄZđåWOka£= [iaË]îA·Û–KôØÓƒU5VNe‚±]PÉ-6êS)*²r6בº n™̉!₫Œv܈?£m5ÚI½s>9ñCzip—O×ë $^ ‹«ä‹?h0àË×wïn‡₫¯Wë¿Ëg›ë«ëa¦ôvùọ́—åó‹ÎûDzˆ̣‹r›†üè2„¡lÛgÙ>ë)ĂRle»PWGï²Rl^:›™Œ—Ÿ>­Ö®>ǧ' H¦Ñ/˜̃x{ÉJmKßG‚ˆD§Ó®ÆVñă2nơY4T±ªTùÛÊĐ)•A4pv*iLüÖ§ºn«H2ü0RSêO#èă%Ö$6 7jc=X&X«ÆÜw%6¦æ#¼ï*¥³íßb˜Í¤³ơßbXé§óöÀ-SX?§–‰ÿZ&±(̉ü?³¬–5÷ÉUDÂZû°"-Zë³MúN]ưL`Q¾Gâó6Ág}PÊ~¼́sYn9æ¶“₫P{úƒ endstream endobj 385 0 obj << /Length 1480 /Filter /FlateDecode >> stream xÚÍ™Koă6€ïù:Ê@Åđưè­ E±-RvÛƒÖV£¶´åûï;)Y²dY¶7C R¦8¿28x pp{q5½¸¼:PÈ(L‚éC@•@\Jd¦óàKøÛ/Ị́ïëḅïôw‚‘ÁÆg1I`¶r(vĐöó_̃p˜JjGGœD "&–Â}t…"Ø}ˆpPưåA³{w{|‰Æ8¼Ê6é<οÿùp“Oˆ“äóíưD‰0Ëç-ùĂÓ]̃Ơ´…aN-ä́Ơ¼9Æ5+s›8%ˆƠá,°û˜`ÑúhÄ4­>Ï“u¶Ü‹,ưi "Ă"ÉWeS…/̃–”#Lj @©×e»ŒD$•jŒÂ«¤xÊæƠø%ÚÎ1#h†7îû»¤Ø€§E˜®î‹®i¼´đÅ$¢‡ŸoƯóeBp¹8eÏj³H]»x̣C×ñÊ·̣ä8&I‹Øzƽ‹×ư₫41%+Áˤö)ᆵÜu¬·’¢·éu¼œm–q‘¬wTüêWÛơ²‡Ÿk#{5… …U½O¶«»³$¬vdSDߤT!­X5ÚOÿEÔ’‹'7ç*›o–ImJßôB#®Y7Xû„…$ƠXä¼ËÀ„́¸wjưŃ !¨̉dîzÏ*Âx¹ñ?.ÖöIĂØu·d{Ö/ö¹Ï/DR$¤è:¦½•Ú‰zÍ«ê]D¥ÜÊw¶§^©Y¶J¼̉6¸+ưʆ ngt;¸Ë)úƒ`¤œÎ{â@ÜXShËưncĂ₫à̉±×±è%Ú¯=‚»× 1ǰT°I^,̉G?WIñ’$~«̃…%”k+×;Ài«n©Ë‘ö ƯXÊd›ˆ):f­]'Î×ø–gvÔób^¼)2÷œƠ « {é¨PM’úOªˆ̣ị̈låZë"¶»Üë¬WCZœZ9ßmb»D5¨ï½8K= ¿Æ³ÿü«Ç Äÿ"m¬Ư6oZđ«W ‘Ó×íooá5.ÏL˜ttÂM[@´J́Ϙ6ƯJ˜Møï¨O ;”29Ej ”yœ“"N(2Zµöñ®út½ßY¥¡üGx‹̣rܼO}áu/·M§èÛn{̣¡)aÆ%¸ˆ@el°Ú©ÚÀ±ƒöܧ¶¼¼#\3¤ Q¹hDd­ci.HØBÊéØluÈÜo^Ö;hc(%P†“ùù6ơDë2É—%‡K̃öÚ§k·.̃mëz¡æYUt¥Yá³§¤BäËSRA¶»– †Ñ|„?¡f" Óâå̉t /:v¾(k¸½j½àˆ°ÎÊó›nùMÏç÷»yv°t©8<ñU¹xƒˆ₫Êø®"ødG Ñ{tª;÷l£ØÙ́§ »}<̃RÁneôAv3ăuazø8§as9â4ljl±$4 b:&[²–.¦g̃Ën.ѧ²›aéhV*`Ú1“̉–÷~$»9FöƠQgăZûăăb̃wáp¾¥D’³.¾Ùéøve÷tbh˜Ut€CÓ{PÜ«jœjMöJ@Øcù&Ơ8œ\…2çư¢ºdhË¿W-É1C óS“m7O7G3Ÿt©̀(ñ7)Đª¨Â|TA-t Ê-?ƯŸ‚°D óq¨•‘íYy…ĐÛ¸u ½h‚EÂq`P÷6ͺ÷5jjéA‰ckêa27e_•Fº2#ï;g:Ôt!ÎO‡xU{Œß[EJ%J!ÙÖ0̣u&„Tiá}̃øø¤w¦¿¨@Z°÷á÷ñS—à…µ¨."=XXK5¦°¢})̉”Đ=FĐư gH‘°‘¸ùß»²Jomz‹v1pG}/B F´}’zư[‘ÁÊÚœRYï'¸4êd‚oÁàŸ¿N/₫i"´ endstream endobj 401 0 obj << /Length 1728 /Filter /FlateDecode >> stream xÚƠXYoÜ6~÷¯ØG-Đ¥y‰”ú–‰Ó¢I gMû {éµPyµ•´Iüï;#RÔaÊG8éƒÀCXÚ†Êa—£÷v#;ÿv¾E¬&Àe·.MÁS‡{öưR¿®–,‰Œùóô7kù!î^äøuª‡Ö@Y Å„•…„¬j«Épû~ëY×M$XÑOª¼ÛÂ9Ç ÎÙT×mUG…×áÖÆà²<Cgö'Ú3K8á\ FQkưnü„Ơü REèg¦9Tx»úçÿHM˜ô.v^–…ÉvÎ…́¯Ñr'èaè¾\"~B¦’˜nÅ¡9Æ;‹„(æwÎƯ¢ÙΖŸĐ ³"GtqyLÂ/4IVÛÓÂÊẤ¶Í•ÁZ{YAƯÀr9¬Ô-„x2MHL=̃đØĂ·I˜¿Œ@"GY‚h61èu¹9Æ£1hPM¸ ø^4đ7~¯; ăåmØ̣¯„퇥ÛĂøÀưÏÂVƒR°È`ûÙÉkS¸kÁFwc–ƒEµ–?fădAI®f "pï4½%&NÂ’jˆW\2ĂBá½=<ñ'âË"ƒ`¡ơ­±=="±ƠcPb7‚%W’¨äñ loñÛ/jh‹•H¡LÏééPtcn!ñ1èÛCÑäûâæ´µlyØ¿*úƯɳ‚±—Áí}w2 KÆ8Ñưq —_(oB;§”°TƯw‹¦)a}`ô¼ˆÜ—ũ â(Ëîù®i£̣­½Ă÷ëé`̃IJVẴÁjuø|QÜàK0¸&ª?Bbp”hî™íf.ơºcà› €W{¡+¼fÁt;×°ñ°Wªt*¶×îèw°¼hf₫nÑËlƠæØ¢¶e1\Ï"¢ÔQÁ´E‰èÓ¡n=́œWĐÂS/ô ̃câÁ½àM<](¹÷¨Ỉ´çH.X´nmŒ du}¸6®Ñ\eƠRÛƠ¥x¨UƯuÙö £ƒ̃ILdr¢@Íá‚´N½)K%vec+6 §­ÍäWß4‡ø€Í¼¹’âwâDŸ_'¢d­TDó™‚sÑùĐÅÄ'·AiÀ­àÚº‡(EÄ('yF|a£‹í­£Ørà–Đ ¹eˆ=Éó6Án¡`le˜…L ̃-ûàát%%Túkçs̃æĂ=<+‰•lcÄ?ÂñÏhfˆáÅô¾„=`îCÓmHh¨&jB?`:®ˆøMh̉ñô¸ 9Ø ºơήêfX rçƠ¾#AyîLJ5€:z’„ 1á ÙlÂ@‹pŒç¦ä?‰|ºL臣È’€~6%Ÿ3‚ùçLî¤ ®Iơ}1$Ó©äÿsî‰oSçÜXñ©PđYI“¤'ùÙ̀K.ơ˜z{ø€û<ơ`cúpúpÙK}ø¨'†¥G¶áÈGˆ R[‰,Ë´f„‹‚K1>Æç¡¦5¡=X&܃iè,ưÄ߀~¸fÄ`Ô#èçey@?½ùưrư<3Ơ A!À|ó#¡.Ø·xQ•÷ñ I§ç,b́̉–ưÛÈÓ“¬¸8Yƒ¬#µc¬œ»#Á–Í F¿;ÚĂŸăçTüÛ ïS±Îză⤇ú|'Î¥w¡LÁ§V|"ÔÁ5»GU§û́‹N¬ơS^t̀L÷Ÿ¼]¦#Y‚é¡îÊWë£ÿƒ̉a endstream endobj 418 0 obj << /Length 2019 /Filter /FlateDecode >> stream xÚÍYYă6~ï_áGˆ9¼)íÛLc¦“`¶ôdhlºmD–Ĩ̃_¿EuZêc‚ÍäÁ`ñP±XÇWE.îtqsơn}ơ惆$†²Åz·àFiF3’0¹Xo¿Dß¾ưqS>Vợßëïa9]0JàzÁ‰Đ ¸ù¥Ü¸EW4đóAÆ ¬”ânơJ Fx¢+¡H¬~ô¾#tÑüÊûE¿{wsµøeÅ(¥Ñ»âœoỌ́ñ‡Ư‡rÉâÈÚŸo~Zåööz ÀÓ ß|HLÿ0t±âĐcå"xàXö× Ùœ·/ ÁP_©¢ø9£jđ=OˆV¦aPÚªÈÎơ¡È¿Y®ÓQmË£'Môœ&Eà’PÖÊ[±Ö4%™Œ‰¤¼·m½/¶Íú‘•:₫+‘hR¯˜ J&øư­Ï måƠ?¦A;6»í@ËW4úùÛ‡%£N5Ø;äØVuêôFK{}ؼNBÜ.à1Èw ËumÎYZÛj¹LDỡ:‚GŸ‚9p¸Ø¦[& £aF6'è”?rxC8oµÚßb)›·,i§cˆÄ¬eYï‘屨³ 8l3Å]S¢„¼t¥©M”!Z¨f-Y®dGkÔŒ{œÎ5îu¨Pñ"îJ5ŸVƠùhƒ¹êÛOöFơc0D^ÔHlövó»3Ư†°s>)‰‡ĐÈ`¬… ù ÀX·ÖHë1Ơ,®|›>¦å½½)‹óé®Uæ=M ÄNâ¤U>¬B,¸o/Ćր3+B ´’ÄfÑ:²Ô³ºƯ{'#“ ]ºé}Z!Qäáƒt»=¸ù4Ă₫¦8`2¯‘É&Í2; ,h)Zḷ—‡ü~̉Ÿ(1̉ZEï3{„}v؆à BVa†] ư>¼€.mêƠwi.-­"¼/ÂÀ§Gl³CU^n{Ç$èÏæă)$u ễoó{øÑ0GjS”¥]ùSÑáq*Pơ¶2b{€M«6 üưù6Q+>™HVñÛÿ›m¹”đ^agW”H C îmnËĂ;‘cÛÛ4«@̣wד,{̃éwÚ½à2‰₫UƒơûÇh´å5`Œă~D Mlâè¡LO'[V8ŒrQ́æà<ÛuºÓCçaǾñ[**̣́1Lv§ê¸9×<„¯/…OXp X·+²¬Xr=„p›=¸†3*îé0­n‡¼¹ڥŠ´Å̉@1ÍJ›n· ̃j[¦¡/ ÷̉‰¡o‹Úî\<­Ê™&%¸1¯­nÎu7¹Ăơ0Y…éƯ9߸+́n ¨p2í! Ơ¤A¥>àơ3H/ØÓƠ¼'µ'ל®¨K¶D›9{Eî¸ñ̃î2X₫‡ƯƯ É₫É:“¿¸ÎĜԓêL'Äe&Ôˆ|®4n¥4†?SNrΈơŸ-'Ơ—T“ Æ8×nâo²0\c8n•nƒ÷AçDJİĠ&ñ¨Œ¿yûăL JÛZ®œ›yakBøaÿ8{†9Èq.kb:†­÷:¯¹ûºà¾çS?æY'Pö™z²3ƒ́{̣À›Ö%Fµ{ØÛ̉N1äè\ànQÜ—®QZ´¼ †ĐË\YmˆLÆàƠÀxw¼'±ŒwXÆ_eÿ^;3₫ ÛÉ8” Ä{q®z°zD™ç<- s/ÔO£qoEñ×yûüT™Móç¡gâpBwOåÙNVkIÿ¥̣0W¿̃귯ΆŒÖ¾ßûÇ$MCă¸*…Ï9n$Å&°ô´Sp«gK7Ü€°ïà5Ï;U~N7µ»zÎyóD̉h#) Ÿ.ơà(t«ƒƠdÈBĶ̣_ UçJÁ$r/Ä ·oÅ%ÜO÷¥s₫]Ís’@ »»ÖkDÙvç^~¥”o ˜÷O?•¢X:½ 3†–‚Hư‹}PvÏsû|=<Ô(Ê…îßIƯ_óºk\†:éÆÏ,4i.J̉4  M[a‹w·ÄVøêç&g4Cu/ØóÎ/ 1mܦMẾ›bÓx»Ÿ ±-” 1(~øB;ÿ o6₫Åÿ©¤8‰Ơl¥—°ø"»È/̀.ífÛụ̈J!½2»€ăr¦fÓËÜ_k/*q(´ùêÉ¥³Fh߯¯₫›ơ endstream endobj 432 0 obj << /Length 1777 /Filter /FlateDecode >> stream xÚíY[oÛ6~Ï¯Đ£ ̀,/")îm-Ú¬C/C` @»¡PmÚ1¦H$7KưEêI–“6ÍĂ‘Ísx.ßwx‚½‡½ó³ç«³g¯xèI¤$&̃jëQÉQ =)R$đVï“ÿûo®³Û¼Xü½ú–c`¤°²ëELØ­\JC³è »ư½e@ĸ̣–Œ£Pp»êB‡,Éí~aĐ̃/ ˆ*UmWd=(UvµĐưÖ®!˜·dLeµè&Í6C[1‚ˆdƠªË(_,…ä~q©í`›fWføéÖ¾‰́ăfA°o6-g½WéæëúwCêQĐO„´’œé<Å>M†´RJÔN%lFgptî-áÉå¼]¿‰²>Ï̉Ăơ…ÎÄŸHµ´»uRDæh±”Døï̉ÈBD…q_Ø7ûÜΓÔ}(t^èû8â0"đc£!¤ök´.Qß:ñ¹•Ùií#ØBP`$hĐ5‹±%娒á₫­Ú8ƯŒFœ₫ÀBÍó—H°úTÈ. B@qNKJÄ ‰l̀́̉ç(@ÜæÂ^ơ—í¼öô²́Ó’`Œư×ù«lAB_ëçot‡ø 7&0^7_JÏ_wRtzëg¯”lŸƒ†0#´s˜nøÙau^£TG!ˆ»& ¯ÿƒ`ŒtÇ¿,–bÏx¨J?.wÔ@‡ª Úd‘ÚA ä̀ĂíUøJ—é¦Z_Ûʺ­•hL „]µ±Í„R’ÿ: D¤9×—4u”ØøtŸ:á9• ̣€…G¡R Á[H¹d̉#ÙØA”™#Gs= kxl›º£ ‘°NÊ2 ¥MCx¸Ÿ•cc^÷ºAPæÔ.NvÅ¥“̉VS÷¹Æ¼~¼È‘"Ë ä+6̀QÉ©àÚ Úđ„Ả®{ 6FaµÛÆP`¤!¢ZC̉ä“hM!)å(Z\ú¯‘v#ƒÑ¥"ɹ†£ˆ̀0b vM¸ß(ßq¿Ù‡³®Å`6a¢kEë+ĐÖ"îÍ̃xÅŒ´I£àcËi¢í ©̀ĐËwcC\Ûp9ˆÆÆµ¢ßt–:YI‘9)7—ûµÓ ,î§ ˆ69E•uª· Ê!S0]ïA±aÊ€ƒ"©¨£ ÚP†¸'e|X˜,̀6?Œ4ØÉ¤ñÁ©³ƒøŸAlÅÎhj‹~±uŒ1(³œ=”1:ÿpÊp´ZHˆW›ÙM#™Í ,—Zñ†böy]*Ù¤h§­Áç²tÁç0DD̀ƒgÚ†g³gÏ¡Z`m×âÉ‚,˜.Èæfr7»ä ÙơÖèpßö˲f 0Wç×˸xYרëT…¬3Ú–6ZÎ(̃¨¹¯đÑD´<âRq7¨$o.Gcyhî bFf9¸?B5ÓÉ̉ïcÀw/>÷x}ÂR J¼%ÜøI÷° i[°—ÍîçöYUŒ%‚9¸‰£21vnéÎXĐ»ơÎx1íü³×È(µ—|JI§°éă–„{đŒH"<µ5L[D¥.¼«psĂ0Ơ–Ù ÉRˆ‘zEYÊ›]3wS(¥9±æm‡†Â­ª·ï^ØçWă"åÆjåï6©Î­ư(&Ä]j)/óe‰r©×ÿTƠ„ɘí(’M96rAåÉÓ€R0ơ á3¯éP¬³¦áà:¸eغ•N†CHj:ZWúâT:QÎù 1Ä%^ø ª ½'ECdD M8ÎA°`@9CB¨){&áƒư±<ŸeË’ÿlo¿.™Êú‘ê Xn™˜>j5­Æ©§éJ<|Ôù„Ă1´›”w!T!ÙđÏD®+;öi˨ô…¡©9& ˆƒÇv«m 6n¨-9+{–ƒ ¢Á‡’ƒàÙå µ9(€öHüê’Đ¼»ÛUÁ7B@æ¢+äƯ¶´:€Îu¢³¨H³üưömy“{¿½¨­đZÔw4˜Ø×qέ§¤›é₫Ă6 ·;—# ÜVoăQ›Ôñ>ï…¿-\̣gUôäß»R¿¨±„sªÜÏu©…pZpØ¿̣›oÓ̀F{ÄÆM7|~ØlÚ4!øDBp~Â…ZMÈ5áÀX,Ơ;ûjÚQ|p-B‰Ê.•{*µLó"„ڽת¶8»®̀Ơ8³í}²ë ^>ˆ ønEJđ ˆđ<=$›(»}¿­Sï ´?îhe₫CÍ̀}¢bVï1¹¡4ÿ_UÔñ¶Y¯É1˜pÛUÍ?=îiµcº¢ÿ¤fíỤ̈²®'NÎÆÙîùruöUrƒ· endstream endobj 448 0 obj << /Length 1094 /Filter /FlateDecode >> stream xÚƠWÛn7}÷Ẃă è2̃Ù·Ú¨]AZ$-EYB%­±ZƠđßwxÙ›²R”-ÚayÍ Ï̀œ!iö˜Ñ́îêz~ơæVL«)dóeÆ´$BgZ± ²ù"û˜ÿôĂ¯ơ˾™ư>ÿÅi”Xj£{Ιr‡a0Á~C %ZÊ×r¨üÿP(·"½7¬¾7p^Ăm·q[Ô>!Ăˆî_=}j¯Ê ‡ êŸ*@„2uQư®^çÖ'X$Ñt˜É·' øÅo ËíD½â>oª‰9fÎ6Fb„₫%å¤+¾JW|Å®øª»âăV¼â«GưÚYÅ,S⋱QDé ơêĂKAù—Bø 2Óo&Ọ(bb•ùgx´g°ôưq~ơ7w¼û endstream endobj 456 0 obj << /Length 2092 /Filter /FlateDecode >> stream xÚ­XKÛF¾ûWho`uúÍfn^ïÚÉ"Hï ÄÎ#ơHŒ%R ©Læß§úMróØä ¨ÙlVUWƠW/¼:¬đêắÿÿyóæ›\­(FRR±º¹[ &VRÄh¹ºÙ¯>¯ßm¨X_.ºÙ×l¶Tàơûͯ7ÿyƒ^…_wX?}ô”9*TA e¼Ụ́)ÂÑ÷m3tƠn¨›ƒ£ù]{n‡öRë̃÷2Z2„#Æ%ơdDDD^ Ëêó–`Œ×7GmNó>&*)*¥Ú–æÏU7ÔƠi$¡—íÁ}<ˆ”©2~ü¯j¨Ü…n6_?\ố:¯F%.­Và¤@JÂ?G}o)æë‹Ă<°ơn¢.x{t"m^?¸ºwG+÷¸kÏ—¶ÑÍàvÛÛßônp¯†cåW_›Ö÷̃:€~́₫ïf·:]uïÛ»í§¤û3†„p7j§’¾=k¿º̃ö—jçŸ,yø÷ëtß®CƯ6h³e@óûÁ½8V½[ ÷†UëÎU³¯†¶{pñâư·Ơ¯ˆ5S$ˆ—ê ¥bf0ÁÈ8%¢ †EI*çSCJđtV„Ă•;2%W Pđ'¾«.Ÿ$HÄ$¼?Ö»£×ÁQ‡ {k„Cµ×̉^Á˜6z¦Ø€(©W‡ü¿Ô®sߨütgà±!ë„éMˆ4éÆ wªû!Z?£- >ú¤wm·ÏQg )Ạ̊7¿¯‡ăÜrLG‚Ǵ"ç’9&E4ø[QpÍ2;W—)£rNY´lYÁárêŸ?è!˦@RD™9 IÚ[ă&JX½+9Ă.́O°+ˆ´åDÚXi?8µí×ëŪۓΠE1E8y÷+½C ïc!¬Àh?ØÎBöîÚÎ-tµ;zÍqűÆáfĐƯyX"Væ y¸D¥ˆ¶9>ù#°[8ư ́«…à[/Aă9ŸÛNaª,wHQ•8˜¿9 GC6b´²ÀÉk’¢‚"Á½$ƒèD’¸Oë1–jbI‚†¬³G$™ÚåZŸôÙf¦– 1RP¹à#p¹vÙG$R*jƸpU7½c\9–‹vËÁ߬†?‘©dÂ'đ_@đ₫·œJˆY35/ÆUL xÔ]WP2)̣"q 6”2Ÿ† L‰ḌC§ơ/ÿ·\E‰$ÁƠ¢ È £@™å̀sÀ©ÇgL–y(ÆYscp°¨â˜Úla˜;pĂʉSxpĂÆ¤nà\ùVÊQ1”SHÉÁlêÙÀ=6XƯ;dqÆQ …̣ÄäÆ#)ơάŒ¤Œ’ơÉB: c”TDÖ¥̃AƯ£àá®f`m¶ë-Y ̃O©z³PÎYeiL@5eöD´áX÷s±«Îq©ê. 1E9}>¼­Ï¿.ø'ćYw‡̀# Œó©>9PD_ëôtdQ¾…d` ‡®5‰‹1>NæơB₫æ rXôÎúœƠ­±w±Äغ¢YÔçê k«áñ»Q½fL)÷¿­;¸œ—‹œ ³|Vá[bNcm DE€gÄ!ÊñŸ¿f’©Êµ5·đhq©B̉… ëQÙ„§•_ËÀ“$ÿ³®>\£¼”P©×_è‚¢[t£;Ó\,\ r8Ü~ïë)‰~uE”s h¨N‚;Ÿ¯§¡¾œjm³‹Ù*ض‚çcÏ…ưèoáÛÛ¼—€%i Å ø)R{a±äÀG„i³*…5•Û ĐGµ_›½îy¿QokvÇ©+Wd ̉íDk™2•Qµ₫±lYUo2T{r½÷Í8l™FÜ®̣¥ ‰ ö¤Æ ¼g©!ë²dȸNYŒ XFÛT—«i½ô¦gûcC ́ƯFº–ḱ È#¦?ÿƯ:yE˜đÏî́ùÚû¯n=ư₫¢wµ¡È̃>½yg%%¤¹³B£Ç$N®W™ÀƠ®¬\¿;ơíÛ¼&$’É UApD_£­hÀËë¢LLƯ¾3,,À[®v4g|¨5Û̃Ớ ÷rÚíÀ~Îàß{!¯†!t̀tqiû¾6 +ăưøá·khdû!Öø¾É½­‡i#R7ĐĂœ«Ô«[†Ø«øw×̃Ù*ṇ̃áHϺ¤́Ôáê~0A Ámr‡w‘Kà₫½ÈΫÂ0Å1ô¤÷q¶eàäœz>›™¸³®zï{ =Û}̉@Ă%́m¤…’·Äi¼÷ª_©üt·0¿‹ăçÆ—e1vU ‚Áä¡Ô·?Îgf™F3Y „›cʸP%‹i‰­eê“ñă”'P¨qÏÙ¼À~d ¡¼ŸÂÎáülÜ:*#ôÄxÚ^̉õ3FnÜ„mjưaB₫»MÌ_< ³#_ñ¨5K8ľÎHÔ¸§̉ÁÂïGªî•¡}ΔF—ŒA…RSå1‚;óÙD È2kAfL EO/ÊlÎ{øÇto‘!­¤X›ÿÇ0óÎhÂ}Î~6êZ“ÿà&FĺÅ`{4³UÍäymàâ©™J‡ø&ˆë7í²HÅ e«4}Ê÷”I)ŸÁ%åP¢³Ạ̀uêƒ.¢RÍ"ÿߣÅß/ëê–Pư7êQ<ßÔå_ oAQ¯‹o7! /ölªY&Ÿ/ 1 Z¦#₫i›aæça,kÎ…±lñ—.fÆ£ÊOøœù÷Í›?®i#p endstream endobj 466 0 obj << /Length 739 /Filter /FlateDecode >> stream xÚ•UÉ’›0½ÏWp„ªXÑ‚$8&©¬•íà[*l46QBNÊŸ–˜ÁÁ‰sR#=ợúµ É.¡ÉÛ»—ë»çod‘hRjÊ’ơ}µ$¹N´b¤dy²®“oé»_·îÜû́ûúÀiÂ()i‰xÁ‰P ¼E¨`tGÿÉ*g9²LVB’BID}´ö¡ÏV‚êôÔ…µHữàÆCk3.Ó_-~v•óˆ°÷¸3!·¶ơ®Úú¦Ư!boÖÛ.c4=c®ŒÊY²¹ –c²₫¼TW^ÍĈ¬Úc:ăO®í/r̃ZçLßÙ¶¹€7(|ź™ 2/ÑMs¬v†d+Ieúɺp›©´sfÛôKÍáœ)™>ƒmÁÓ&ÔÍä“đ!Áˆ®ĐŒÄ g‹UsED1µhgZă*oƯRÙÚ^êê÷èùñ jæ2Ÿ³±•P9˜£i=̣ÀuA„.æ<85÷€1@++yºYî—’³ÄCsX́'qM‹N½qÇE· Y¥ƠTä»P¶s¢âÔÖÆ ~CÍÁÚlª~̀Ä]„6ó’¥ë\W¾¸'bçĐ#ô?ZC[ăÓ™¶î‘F¦ÑE4Sd¡N.)按ÖÊ7ă!„X¢€QE¨P7M¨g’Eo¼—j¿J¬"RSèªʰ¸n†jª¡‚d’Eºñ ¾R<1ߦóœh.§ñFÇíß„×çgh₫Œ/å J¨¼E¨xq¶…1₫FBô­âE+¢äÄà—ͳ]|œ…€±³̃Á‹̀aLÍ{e* ~~…+2àú($Qˆ´¶qæá¨µÚâ$ à3nn÷fû0 ñî01Ù´ƯÉĂdhx4§ƯbÔ§̃ạ̀²”á…=åÿgøÇ=¾×4́(蘳ó?RrCç`ûfsÏ=ü ̉÷·‘Æ`Eƒk\V´È —ú]QHb̃éé'<®¯×w¿÷Z" endstream endobj 473 0 obj << /Length 356 /Filter /FlateDecode >> stream xÚ­’=oƒ0†÷ü ¶T‚é)¡êUR‡(ƒE@!$ª(ươ=pR uí€Áwïïy G%â([đÇ{™/¢µ¶Hj–ØD üˆ’˜eP¬c¦ “ĐoưÑwDX́ÛÂ÷dŸ¿ÿvˆÖ†#ÁYÊÓ©œ#jÓ¡n·Ê6û™í¨á/ư0Ô­#4 ¯êâôB¨à‰Åëεß!œ¹ªS5Ç!™b×Bê“X}×Böo j¡R[‹î̃a#q5 ×₫5n·‰ f%1Ø]é8R† e†±{¨ơgv™ËèƒĐ'Wú> «á GM`Œ£đ£QW¢y`;!«˜c=óá×ú@JfDüô­i₫ø*‹³ÎUî \†cƠ=0ƯßÜơñ5Â+¨êf¸´¬ưª'̃f4è6.î>¹PûªFS¢ÿA‘°~ À¬}˜©äL½Ê?ÂEœ̉ endstream endobj 536 0 obj << /Length 1494 /Filter /FlateDecode >> stream xÚÍQo£8Çßû)xl¥‹ æ±ínr9µMƠFWéV§ÊMœÄºº@VÛo¿cpª&öö¡…áçñ̀ø?ăÚÖ̉²­Ñ™}đy5=û4t™E\ä3[Ó…å{ˆ:Ộ|á[Ó¹ơơ|ÎÅ‹§½?øiHm Û(°ƒ́)ÛPŒ°­à³TFáÅ€Pûó¶ă#ÏózÑơ ֑Ọ̈̄.;ëa}äØN[XS1ÖÖÀ6@e”Π/Tm½p_Gáw§7YÂO£G…Êü¼Ñâ±¾̣H[/¸³–±"›¨˜ëôE©­ï—" ù¨ÉêÏ_̀ĂHoµ(·^æĂxUÅ(@ơûÔÖëë*¹íƒí-µơp¾ûß6WoHTƠ›Úèú+œøkªLV q₫Ïr#£Gú±¸F^̃„عmsĂ$NsÛ…=ä3qĂÓTÎÄe8¿,?^®¤xñ Ÿ­²C¥\ 1D}ÖF 1䓃Ǻh…6T¨àXè/?G.ƠÎ7àÆ̀FNĐ6‰°iÿµơÂâÊHU£—áë¬ßÿ7Á@‰äÄ/È8‰h#ToCû}ê˜Ă&qèbälvÇ®₫=¾BHVï]'ÁeÜ»àÚO‘|@c%“Åm4ß́ZL"‰Ö[5đ¨nâZï]=;¾‡Å|#y8Y\BåK5Iyœñ5ïcpÇ,UÜ@qV¬Ê%öY1¯e(SqËÓX₫O¨Tꉀ"æ8= Bà¤ñ˜[²-_ÖB…n¶j|~%2›z₫,t[̣̀À‘áR¨̣]%^71QLüĂÏLIù6±(¼Ñe^₫oÓU,’U´›¼i₫·ïˆq¸ˆ₫¼¼ÏÆe‹÷|äµ.zÅ2b ´±€ ³¹'W̃ïd¾b¡:WƉ¬T6>CÁ= ¼´ñ¢ë HwJÏNE¼¹^‰Ù5¯ḷ誅ơé°#6K¿§ÁGV,YƯâŸañæÎ<ëøH_¹¶^JùTÑuÊS̀́g ưÈsMUY˜ú9á)e¨iÏ÷eh™7W)-Ăwë@X‹90î‹.`ƯƠH-wÇåaÙ<®œµ™@m½°Å H+Æ Ưí^‹ÄnÄúÜ ï«P°“.=8êŒç‡ï Âܾj1 €P?Ú Ï'm¨~{è¡§1½—¢§N/mư8ÎäêV¼Î… ”ôDQơ¦mèÓ¬¦Á¨†¿ªư`Ç·;èơªÛ¬ää£S"iăF°ÔÉ.Iúj>vÖÀơ~§ê7¼S- đ}̉œÅ̃úÔœÚzáÆă}ú|fWEЉD úT~É8TIYRủcÄp1÷‹ưzaUGÓĩMZ̀»ß‘¯Ø’¦ăîNÍ)ÑÁFA­Ăêÿ¨  l=›sœÂ¯¿LÏ~® endstream endobj 382 0 obj << /Type /ObjStm /N 100 /First 875 /Length 1648 /Filter /FlateDecode >> stream xÚÍY]k\7}ß_¡ÇöE«ù”!̉ZIÚ<¤ÉRBƒ̉ß3×j‰½×â]BÁX÷ăÜsG3sF£»âJ’¦‰˜0zbŒ51îHkI¨¤Ú“˜âcÇ¥^’*c¤¤xD:'“²‘.É*p]“Sà,¹ÎS-«©Z¼N@©IKI #'*T®SqPÑFÚpÅp€÷(xˆÅqPqĐÜ ]Ç “I `"À8!Ăë”Àl f³µƒÙ“ïxÜ+̀%Ô(À¸̉ƒ‡AØ ·à$ꆃ .0p¦p“ĐFa SаÁ™ P¯z€ñ”`Ê đ„rÇA¸‚€Q9°„ NU¡‡ẦẦ˜>·`¶`Æ“ÜávC\´àPÅÔ ./+p±Ân!Ø¢XQ-UKÂđˆ ¢ƒ×ăVM"5B̀µ0gáf°‹…› „î1z¸Yän†¯¤1l¶é!ˆs¤ A^àÜ0­XĐơˆ®Fà Fªăm.đp=L̉Kç8l$ߨÇ̀âŸcÿ\ăI€+ª%n¹Ái8KÚ +₫ly¼iñ*; 'SEs8¹’N60X(B«'ë5y´¶äˆ1zr éÚđ8\æL̉Æ YU6÷îm¶OÎN/̉½{iûn äNIÏâ¤D–d;!K/O hœ„JÍÇ …"àÄ8»³}z~öúùî"¤íÓÇỎöÅîÓEz¹Á­xñ‹¿ßïpăƠŸ»ÍöŒØ^|@„–Ç7Ûg»gÏ_ï>,̉\.ư²{óöƠĂ³Oé$̃igÆô›Rnư%̃öêK5øxËăt¥d1đ×ß~‡Øsx¯VÍđßéÇwï^̃ơK¨Ô\ è),y\ÁºHv¤̣¶PFT§°f=£.Íaµä‚Z0ƒE¢g*s>C]ÈUl+Úsés6×\'çÆêơbËœëơ¹ư¿” µ§ ÔŒƒ”«Ư¤2®BoWÆ*–(ê× Ö­å¢s6¸8"7Çkq™Â*œ(} ‹’iE«X£¬hJf°â57›óƒ Û£ÀÏ`‘PÆœ l¡ä¹S›N´7Ù̀\\$ʾȮéï3ẽU~Ô®Ë/¤ĂäGuZ~W _ßö†…i 몹«Ma‘ÊX˜|ë=÷>77´ùÙIç°{Ûœ½èQ³LB±ö*SXr¬­Ïa‘Ñü‹µæºDPxÈư ïé@Ê:ÖÁèÈ×V²‹ÎaÔU¬` ¦8ËÍ)¬v$–óö¦R½‚Å̃(—6gƒ©:gv9¹Ô9ÿ²As&Pắ“´ä”¹ß¡?»E7Éé®ÂĐưB] t~Đ:/Œ5́MÂXÁ ®¬ư5,v~—ÈÍëJ„ï9ó½È™9³éÈ]~ai_Á¢Ẓ¡XŒ°),×’u­[^ĂÆ~Ïe KµåNs6JÚ å-măÍơQ¥Jÿå#p•×Rđ»;ßÏAÿªTßËAŸËÁ¯Wă4Weo¾•î2ßíƒÓÓ30,×Â$¹fÁ‚ÛlŸüăb9ÿùíé_›íĂ³ó7»óåMååöÇíOÛG'´œ„m¯1©Ø‘*ÚÇ®”£×³NÉ–ĐNÀ=X¼÷øúà냯¾¡p탯¾>ø.?8%;z»ü&…‘Ç(cÔ1Ú}ŒuŒmŒƒ >|#6Bh4øhđí•Ñà£Áǃß(jƃ>|<øxđñà“Á7ZS»Ü­Â06°p•6Ɖ…±I…€¸f-üM* ‹dß :£ÙoX¥Ñ·¡ơ‚Óo©0ơˆ6 ̉Ö¨rXơĂớaß É-•¶цß»déq‘ơL Èeñ¯ư–Pđ1ck e‹o…’AÉw°Ê-6øñl ¬,]9¤‚ (/X‹UP> stream xÚ½—MoÚ0Çï|©4\;çh´º¥Öª1`5‘c¦±O?ç…—´)v¨@èéß¿çƯ†ÖÜ‚ÖM«7n]µ<à{Yă™e{8å¹øÈ±Æ‘ơܾí>Lå:UW¿Æß´9´>ô {ĺ"­–›b'3jÁRÿz@}냰}×ê`¨K ä„«‡Pª»ä‘IÅ₫\¡öˆ©t¤Â$ e4Z†Sf:ù¸®»9¼Sؼ9("ú Äñ Ó)VK£? ºUüRx UüâXrnŨ´¬çM`¡Ẵ»@́UIrçµ§ó¿L̃iß“Ÿ WưƠ„ÉÏƸ# öíSAáaĐzNJ> $çÍRVÆ$ٹͅ’dÇêØÙÅYị0î‹DÉpªxæùüV¼ %–ë{!^̀¥ô¹ácR´ ØHô?£s³–êUVÁ•÷á-%K5+KT¨øofL:rôwŒNDô+„¤T« -E¼~ _®l³#ơÉÁÀ·®§\q‘Ü%¹ÿv}6d©ˆWÙ¯Fç‰ lxj~lÜŸR}¿Ư3ÖT‘‹C/Yˆ‰#†,Î f«!ó²ê&уÎå¼&˜<íç9*é=f)¾Ë¢À7ƠƯj̀Œv;5ëæœ̃DÚ'º¦€–ê•̉Ü¥¸ÇÙ„I: §‹Ú}ù¹®D´ÑÔ¥;įƒ{¨ï =±Ê. ëóẉè÷Á,Ç2ŸÈ»q\_™Î¥Æp©^Yn£Ÿ)mï`&,ä»*ĂR¼ºøù<†F́Ç=µ̃ÜĂ(¥ve{ă)ûµ+÷̉úÎøÔJEö+•lP¥Hæ,Uà£!Ó¨»¹£»EÈ{¦”îiÓ• R@¼ăg·Ëxö›KmÓ,צä] ›èŸ„Œ̀‘ö†øR{§T¯tÍX†I‡Û)®a*Glª„4!PçTJ¯i╈îA¦cṆ̃±½ơ[ ăKµw!~,ÈÖ6Ë]™ ñ¾N¹¹HÿÓ>ÜOt‘Ïï" ăÔơ€«ßËG¥v…çiÁ§‹X0»]/óư¼ŒC3B`zê¤i5—â•ÄÖÑƠ\m¸Ä; _Óç×qëJ/6 endstream endobj 568 0 obj << /Length 100 /Filter /FlateDecode >> stream xÚ33Đ37T0P04P02R05T0²TH1ä*ä21PAs¨Lr.—“'—~¸‚‰—¾‡‚9—¾§¯BIQi*—¾S€³‚!—¾‹B4Đ X.O…úÿÿÿÿû €e¹\=¹¹¤ÿ3á endstream endobj 569 0 obj << /Length 285 /Filter /FlateDecode >> stream xÚµ‘=NĂ@…'raiÁs°-Ḵ‚„ $¨(PR…z÷&\eo‚à2…åáÍ:FDBt¬‹Ï}óóÖåySI)µœUR¯¥¹ç߸.ž¦o^yÓqq/uÉÅ5Â\t7²ß½¿p±¹½”‹­<@è‘»­­”RO”iŸ"§‡ P€DUó@)đ¡ú(W¯¨ñÈ ˆ̉Y€½ P„jH&‚Đ‚t\HÙ´ ̣₫¨Oyhđ?á ™wϯĐÓÿAÿ¨¾ÀG´s»Ë óDÇùâ´ß8Yˆ[ƈ¸A7CͯØv½B›O,Û\Á[óh èäÍ?Ô47­xS7ß Q•¯:¾ă/‘¦ endstream endobj 570 0 obj << /Length 278 /Filter /FlateDecode >> stream xÚ­̉¿N„@đPLĂ#0/ ÀåÆHr‰&ZY+µ´Đhwqy´{áJ˳rœÑR–eçΪӶæ—|RsÓr»äç̃¨Yh±â¶ O^iƠSyÏÍ‚Êk-SÙßđÇûç •«ÛK®©\óƒnôHưls Èø$";%Ù[ ±J!ª[˜:̀‡Œè[V_[¤Ö3ëöw·ÙäÉ#;ưˆE1₫`ëé̀ sÄ₫ú ØC#±!%U$`$·̉à×qC±±™ØíQ1——YL0 yæ=E’ïẦ<•Îúapy£Ns‰m¹¹oàÿ€®zº£onM¼á endstream endobj 571 0 obj << /Length 128 /Filter /FlateDecode >> stream xÚ33Đ37T0P0bS sc…C®B.S ßÄI$çr9yré‡+˜pé{E¹ô=}JJS¹ôœ ¹ô]¢ÆÄryº(ÔÿÿÀ`ÿÿÇÿÿ?êÿÿÁGAU2₫a``øÇ0d¨ÿ@@5Äü‡B‘›\®\\Ë/ä endstream endobj 572 0 obj << /Length 129 /Filter /FlateDecode >> stream xÚ33Đ37T0P0assc…C®B.S˜ˆ ’HÎåṛä̉W05ä̉÷ré{ú*”•¦ré;8+E]¢Zb¹<]êÿÿg‚ÿÿÿ7@¨Ø(T%Ă?†Qjû0Åÿ€:0€àÁÂDå.WO®@.OûL endstream endobj 573 0 obj << /Length 208 /Filter /FlateDecode >> stream xÚÍѱ‚0àKLnñ¸'°FÄÄ&:9'utĐè Æ£đŒ „z×Ö8¹IB¾´×kÿBÎÓˆBẒ'”.èác™ e(…ó sê@q„jĂ³¨ô–×U¾[Ïtä–ê‚2cL P2=€‘ÇS9[3-ÈJÓ \ï-Á`™:&ÆÜ(”#²ÚŒi,³_ñ}ăÍü ăc]Ÿ̀çô©?×í­£qT°ô₫JvÏ&“ëÈß”̀zøÆ×üJ\kÜăbä¹$ endstream endobj 574 0 obj << /Length 257 /Filter /FlateDecode >> stream xÚµ̉±NĂ0à³2Tº%{p¬̉zŒTZ‰ H01 &èØ³ưh}¡£«î9>#@‰KÑ'9Îå₫K–ư¹5ÔӜΠ- Ù9=|Æ…åÍ́E¹ó¸ĂƠˆúơo£¯éơåm‹zusIơî¹Đkr)Eà•xyñ ñ(&ÖÉA¡MûI•̃'Á؆âLlâW?®c₫h}NÅŸë×÷Ö>j_̉gí»ä¨¹$§’ÜJæßö§sùy/ơ¼Ô/sAæ̉‰mUú˜ư»8ø_ Å&8ïøë7ÑANƯp¬âÄŸĤ ÏĂÿ^íp3â-äá endstream endobj 575 0 obj << /Length 252 /Filter /FlateDecode >> stream xÚбjĂ0à ·ø|/È¢M2’ê!ĐNJ¦¶c‡–vV-oWđ#xô`|ùO tLeđ:ît«z±RËZæAVA–ẉø‹aoyŸ#oŸ¼iÙ¿ Î₫Û́Û½ü|ÿ~°ß> stream xÚ1N1E'rai=‚çà]e ¢Z)‰-H•"J()@Pïmâ#¸tv˜qRD¤KóoûûÿWß̃7TÓƯ4…%½5ø‰m±¦ĐO¸êÑo© èŸEFß¿Đ÷×Ï;úƠë#5è×´£=ök¨xæ_ẰV8‚NĐœaˆ £‘k]´s¡> stream xÚ±JÅ@EgI˜f?!ó“—2đ|‚)­,ÄJ--h'$Ÿ–OÉ'¤L±́uf66.Ë!;{w2÷ªË®–J:¹¨¥m¥½’×ÏÜtZ¬¤mö›—w>\>JÓqy«e.‡;ùüøzặx-5—'ỷFÏ<œ„¨ØH0eÀBä-@ êH4PÉæ19̀º3=K®‚bñ*ö«_…>Ï7c¶ơs¢µ FÆôËûuŒ‰°ơ†¤§ô–Æ¿œŒưÎÙhóĐwb´9•æ9Úü.—,dê?«å¡ơĂ\/–fËÄ)—’Ñkk˜ko~àÑ;¡k endstream endobj 578 0 obj << /Length 323 /Filter /FlateDecode >> stream xÚ¿JÄ@Æ¿ba›LR‚|z5/jóàO¤†Ô†ơAAMQ¯­•ƯØ‚-+^'èiHv!æc"NVỂ”äC¼A}̃ékư <ëÎ endstream endobj 579 0 obj << /Length 150 /Filter /FlateDecode >> stream xÚ33Đ37T0P04¦F æ& )†\…\& A,“œËåäÉ¥®`bÈ¥ïæ̉÷ôU()*Må̉w pVº(DơÄryº(00Ø0€@˜ü"ÿ7`%!²P•]ỘÿAæÛÿÙUABÄåÿC\b?ŒI Oÿÿù â2 ‡¨árơä ä÷đl endstream endobj 580 0 obj << /Length 133 /Filter /FlateDecode >> stream xÚ33Đ37T0P°bSsc…C®B.S ßÄI$çr9yré‡+˜˜ré{E¹ô=}JJS¹ôœ ¹ô]¢ÆÄryº(ØÿÿßÀÀPÿÿÿ†ÿ$DÜL20È’4%áüÿÿƒzùDüÿLBÄ!j¸\=¹¹æƒs endstream endobj 581 0 obj << /Length 198 /Filter /FlateDecode >> stream xÚƯĐ1 Â@Đ )„ir„́ ÜD0– QÁ‚Vb¥–Ö‰7 Xxa­L±́wcP,rÙⱆ˜$êb½_‹á@́b>r̉&îÛ°=p±\‰$b9s)Ël.ΧËeº‹˜åD¬Ư˜ gA–d‰̣ º‡‚đ@ $ endstream endobj 582 0 obj << /Length 185 /Filter /FlateDecode >> stream xÚƠĐ½‚0à#$·øÜXPªn$ˆ‰Ltr0Nêè Ñ_‹Gé#02Ϋ88đ^̉|½Ÿv¸i8ẺD“Ó)Â+êX̣Đ¥®q¼`jPíHǨVREeÖt¿=Ψ̉Í‚"Tí囌 ±yëqÀ́së˜ !éÈ™KA‚»çŸTBCG ¾£¿lG ƒ>à‘Mx̀µlåÉܯ>\ï;‰Kƒ[|­º' endstream endobj 583 0 obj << /Length 235 /Filter /FlateDecode >> stream xÚP»NÄ0Ü(…¥ṃ Ù'"—+-‡D $¨(PR€ N>-ŸâOHyE”a÷́Ñáb$ïcvfúærßJ#{¹he×ÉîJ^[₫à®×bc•sçåûGézö·Zf?ÜÉ×ç÷ûĂưµ´̣́¤DÏ<…¨¤«‚&¢ ˜‰°ÀI›ĐvXoTbr rÓ/9ƯÁTéÀ8W:făªc­ëU †KPB—qÔåé/nÅú?„1¬¿8íVÆ|=)1mKVhjcR\8s4%w–°e×9”FJ&¥TÀœÓă›øXZ‰ endstream endobj 584 0 obj << /Length 259 /Filter /FlateDecode >> stream xÚÅѽNĂ@ pW"yÉ#ä^.)j#¦“J‘È€êŒ ˜G»GÉ#d̀PÅü}ú±°0p‰ô;%cûVåe]¹̉]¹‹Eí–+·\¸×?–¸êëéƠË;¯öO`‡ḉ›{÷ơùưÆ~ưpă*ö÷ŒT[n6ˆHF̉‘ê\ƠÈU#ªƠ` „}„R>‚eÆ@3|(Het %‰Ø¶vSˆ§ ÈÏéOÉ₫Æy2ûC{ ˜ˆ©Îp¤ÛW=ơĐïh®ÇnG*̉"bIˆ ‹$ØèH0Ad—LO2³ºDZÿØ9ÛI[•¿2ẸmĂü¬^µô endstream endobj 585 0 obj << /Length 188 /Filter /FlateDecode >> stream xÚÍб Â0àÛ·ø½'0­…ZÁ‚Nâ¤ÎÉ£ơQú3HÏK BAœ ù“äÆép’QJ&® ™2<£‰Y·ñ`¼D½!“¡^Hº\̉ơr;¢ÎW3’´ ­<ÙaYÈHX®Y¦ẀNH˜+aÚa™kæ; –× ́ZH*P`à *©ÖRu¸hiz¼z„øĂÆv€ôŒă¯#á₫sç%®ñ £̀‰Ë endstream endobj 586 0 obj << /Length 256 /Filter /FlateDecode >> stream xÚU1NÄ0EgµE¤ir„̀À‰H€.̉²H¤@‚Q%$ $û&\ÅGÉ\¦ˆ2üqi›'Íÿß₫cŸÖÇgÔr.Gt­t'̣Ôđ+·ÄÚ”́<¾đn`w'mÇî 2»áZ̃ß>Ùín.¤a·—{\ôÀĂ^h£©$ªt)©êwØ‚̀2³Ế©à`Ĺà‘%"–öÔL¿ùüH6ÍÆJm@ ˆFh«ÂUjŒ ê²úë؈Eüøẻh~™rjådÙí!Cfü#2V‘4e¢¨OV¤£j,4Ú£f#ͽ­8c«D¾)̉'ý̀—ß̣•§F endstream endobj 587 0 obj << /Length 175 /Filter /FlateDecode >> stream xÚ33Đ37T0P0VĐ5T05R03SH1ä*ä2± (˜™Cd’s¹œ<¹ôĂL,¸ô=€Â\ú¾ %E¥©\úNÎ †\ú. Ñ@ƒb¹<]*@àˆ`¤&iÿ~ÔƒÈ?ÿq`ÙÔµ—J¤˜¬'…üÇÀđDB̀ ²$ơAD‚| •`̣ƒüÿÿ ́ÿÿ­d₫¶¹₫—«'W ʼn‰Û endstream endobj 588 0 obj << /Length 177 /Filter /FlateDecode >> stream xÚƯб Â@ àÈ …,}„æôzÚS·B­à ‚Nâ¤Îç£ >/Đñ@1¦À,äO2¤Ÿv†RêQÛ’5´1¸G›I3%Ûm’ơ ‡zA6C=‘6j7¥ăá´E]̀FdP—´”C+t%ù'(®€"?ñ,“À¨¿#ú"nHjÎ7x!¿@ư‚> stream xÚ}бNĂ0à«2Dº%P¿8†Âd©‰ H0u@LÀÈ‚5 âÅ*1đ–ºf#Cswv» %ú"'öưùỌĂy¡ru¬NUIW¡ |ÆrF«¹Ÿ…W÷O¸¨P¯T9C}I먫+ơụ́öˆzq}® ÔKuKGƯaµTëÀ¸̃¹·ưđ%lø<5À„hˆÀ́H˜’`XC°YẠ̀Å´°£ă¯xmå“:×@f2” fO=Â)“`ŒÆ¿ïñÑ1ÙgLúe…ML²Y ?'L\#Óxê=“₫À÷Gèb̉€á₫ k¹8ª‹c¹1Âx$ƒ±’È|ËpădêtDÆeÎàü/‡ÿñañ¢Âüá S endstream endobj 594 0 obj << /Length 111 /Filter /FlateDecode >> stream xÚ340Ô³0Q0P04W01P°0U05PH1ä*ä23ÅaRɹ\N\úá fæ\ú@q.}O_…’¢̉T.}§gC.}…hCƒX.OûÿĐPe€̉ÿÄ€k‡ÈåêÉÈ­\g› endstream endobj 598 0 obj << /Length 171 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0´PеP05Q03VH1ä*ä26(˜B¥’s¹œ<¹ôĂŒM¹ô=€â\ú¾ %E¥©\úNÎ @¾‹B´¡‚A,—§‹ÿÿÿäÿÿ€N؃$́́0‰z8Q‡…ø'₫`Œâ&ÁŒ >`́â&Á `̣¢“°G${÷ÿÿ â?Q’àrơä ä¬`E endstream endobj 599 0 obj << /Length 171 /Filter /FlateDecode >> stream xÚ}Ï1 Â@…á a!sƯÄ51VBŒà‚Vb¥–¶n–£ä–â¸Y-D›æMở̃(£ˆúÔÍHg”jÚÅxD¸1¢aü₫l˜T+̉ ª™›Q™9O—=ª|1!w´)Ú )æ Bæú—  đT¡§{@À6\% –ç.ĐöÜ:Z@̀ ÿäZæø|aÙeàÔà_U/bÿ endstream endobj 600 0 obj << /Length 152 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0´Æ– ¦æ )†\…\`¾ˆ f%çr9yré‡y\ú@a.}O_…’¢̉T.}§gC.}…hCƒX.Oyû†ú ÿè1₫?€€ˆû?Tô„øáè*úÀÀ₫à:äÈ!ơ #ˆHƒ—«'W ~*Má endstream endobj 601 0 obj << /Length 143 /Filter /FlateDecode >> stream xÚ=Ê1 Â@„á‘w¹€n^²˜Xb·´²«hi¡(Ømê,-‚q#(|Ơüc§“YÁ„j9ÖŒYJUT΢y˜¦öדTǸ–‹Y† Æ­x½Übªơœ*¦æN™́ÅƠÄ£7¢ñ ư‹¾”àÏq‡̣ÿDÿ€o‡R²p²‘ä,¢ endstream endobj 602 0 obj << /Length 99 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0´Ɔ †† )†\…\@Ú$l‘IÎåṛä̉ pé{€IO_…’¢̉T.}§g ßE!¨'–ËÓEŸÁ₫@ưúÿ!Äncàrơä ä…ÿh endstream endobj 603 0 obj << /Length 103 /Filter /FlateDecode >> stream xÚ31Ó³´P0P04T04W01R02VH1ä*ä26PA3¨Lr.—“'—~¸‚±—¾‡‚—¾§¯BIQi*—¾S€³‚!—¾‹B´¡‚A,—§‹Bưÿÿ?€øÏ$ ărơä ä\A(a endstream endobj 604 0 obj << /Length 253 /Filter /FlateDecode >> stream xÚuĐ½JÄ@đÿ’ba¼;/ ¹@λ«ç ¦´²8¬ỔBQ°“7ñQ̀£äRZ,;În<9›Ë̀îÎGu|´ẒŒ|Xrµâù‚oKz ªÔàŒçË)ssOë†+®J*Î4LEsÎOÏwT¬/NX£̃ê›kj6 ØÑ¨C̃"®ƒyï`E¤Ct>WëÑ ĐöY´3ªè]˜>}vrŒæĂ}Ô©¯Đ:xA­jmüµM¾ưcHúo„¤¨Ù/ĂOvˆjaOưÍMö±b½S»j“̉ÇTt0qºƠ;Ù­'Kjíiyq æ:<è´¡Kú~)§ endstream endobj 605 0 obj << /Length 186 /Filter /FlateDecode >> stream xÚ}Đ= Â0Àñá-=Bß LMÑ©P+˜AĐÉAœÔÑAÑƠöh=Gptă{1êb$ÿđ#CH–÷†Tا©3Ô9nR؃Vȃ–|°̃Ai@.P+Úi¦x<œ¶ ËÙS.ST+0Ú6”°¶±–úâ6kË‰î… ±§å‚$Dâi¸ Qx¬¥7ü¥~qvy7™»+DDD¤Ct> stream xÚ}бJA à,[ ¤¹G¸¼€Î.Îg5pà‚V‡•ZZ(Ú‰;¶²ba;åËÆ$‹'X„¯HógẬølEĐQMaE‹%=ÔøŒ!H³¢Åé4¹Âuƒ₫–B@)môͽ¾¼=¢__ŸS~CÛª;l6-30sofs0GĐ©èzÇ*pR[3óf“Kæé¯¢Ù‚:ª…““w#ÄhI¢¥;3Yî׈½:3]VKq4‡Cƒî;½à¿Ÿy²¿²,ïmÜw–û½%wf’i¡_ đxÑà ₫x¯˜ endstream endobj 607 0 obj << /Length 219 /Filter /FlateDecode >> stream xÚMϱJ1àÿØ"0Í>Bæt7ô¬ÎÜBĐÊB¬Ộ­“GË£́#\yÅ’ßY•C_„ü“‰—ç×kíơJςƵƠoAö{]V¼ø½yƯÉf”îIc/Ư•¥ïơóăë]ºÍĂé¶ú´‘q«h˜Ï H<äŒY­N¢™ẀÍŒ!»#|i~8 -˜€v:Q₫đ,Ëăb#–ÇâX}n™}ö–’‡ÉHÙ’Œj`₫O:AØoªm®"•Äj™¬ƒAk1°µäêxp3–Yäv”Gù-mª endstream endobj 608 0 obj << /Length 235 /Filter /FlateDecode >> stream xÚuÏ=NÄ0à‰\X&Gđ\’hÈV––E"T+* ¤D49â#˜ ‘'»¤@Đ|Å{S¼Y®O7-Ơ´¡“†–-­ÖôĐà3.ư¦ƠÙ¡¹Âm‡Ơ--Z¬.sŒUwE¯/oXm¯Ï©ÁjGû†ê;́vd°)Ă3v†(&â_*rơ) Ô—(éGœÏ^Ko¼NP=€:ŸF±ô#îÈ™b0caúߨ‰`è‘̉ÿ`œu`;à}!ÀA%à˜g‘yY€$âქ‡÷éơ<đ¢ĂüK~ endstream endobj 609 0 obj << /Length 210 /Filter /FlateDecode >> stream xÚ…Ï1NÄ0Đ¥ˆ4à¹8f£•¥e‘H¢‚-·AK|´%GØ2…•amCEágé[ö|wưùơ·[>‹Ü]rù-̉;mzM[î.NG¯ÚxÓS¸ÓœÂpÏŸ_{ Û‡vü¹}¡aÇ@Z€JhD2¼È„$2c4dvÇJàuŸ›N¸Éͨ³Ÿü’²¡ £ñư—Ơ(ÿ³pö7R³îi‚èøj…/M)ÖvAm+«¬uơ²Ó¿Đí@ôÄ"SÊ endstream endobj 610 0 obj << /Length 232 /Filter /FlateDecode >> stream xÚmαNĂ@ `W"y¹G8¿½DJS:TD$˜02€Ê»¾Y%¼AÆC:Îø d)²ô ¶åßM»ÜœSE-ƠÔ¬iỞS¯ØT”kµ₫<¾à¶CsGM…æJÚhºkÚ¿½?£Ù̃\PfG÷5UØíT4 vFÏ@ÿi&à ₫ˆ ø3ȯ9 8 6”ôTP“=B9éA°₫Èèà₫ˆSFBÔp±₫Yv¾ÏÈ́­Ïñƒb‰·µ|•T¦dv©àdp°Qvđ²Ă[ü6¢}é endstream endobj 611 0 obj << /Length 221 /Filter /FlateDecode >> stream xÚU1N1E´…¥i|ÏÀk²¬BµR[ AEQAÊ h±æ£ø.SD;̀&ˆÂOÖÍŸ×ơ—7+nyÅ»kî¿z§e¯aËƯƠỵº§ơH₫™—=ù{Éüùñµ#¿~¼å@~ĂÛÀí † ,¤F€“I# $Hy!p¹9ÂsPØ SlQ¸ S]BS‡ ˆ3¾O?9CŸ”ÿÈz øĂô Ư5I[lIïªƯ†‚˜\…ÀNÍ+*iDê=‹kḉœtSËèn¤'úá-oœ endstream endobj 612 0 obj << /Length 190 /Filter /FlateDecode >> stream xÚ}Î;‚@Đ%$Ópç.$ë‡1q ­,Œ•ZZh´æQ8%aœaƠÄD)öeç—3&SŒĐÈKp4ÁC g0GÊg‚Ô‚̃ 1 œm—x½Ü ÓƠ cĐncŒv`3TJyĨ€́€J6ï$ª¤(úr&¨;«;Ẳ/X™y9pÿơ‰¨áEDí]•—K»º÷Úv6}zκOßYơ8Ëywf.'+ú¶yWana OÙq endstream endobj 613 0 obj << /Length 286 /Filter /FlateDecode >> stream xÚu‘¿JÄ@Æg¹"0…y„Đü!¦¹…óSZYˆ•ZZ(ÚÉ]-r°vABÖùs… .™oçûv›åI{F%Ơt\×tZSS̉c…/Ø´\-iY¶qƯaqKM‹Å%×±è®èíơư ‹ơơ9UXl订̣» d£› ̀yb¤R.ñêaaÈ ùäçàc¸XŒ"ë`?±5̀†éo,ˆ,ª ß«Üïơ°0È„gó_R°Pˆg¶)‡¸Ï$ư.îz…4üƒ/ƒé@ciJÖKJîÊ“núÈyÀ u%¬>@+âÀŒ¿ +ĂÖ0«@®:És <#ŒNÆz3‘›¥̀b:‹ÉÙ%è^txƒßÛºó endstream endobj 614 0 obj << /Length 207 /Filter /FlateDecode >> stream xÚ}Ï; Â@à‹À4Á9›˜´ øSZYˆ•ZZ(Úf=Z"xS¦g7⢠ûÁ?³̀2AØôÉ¥®Ü ¤^H[ø’]Mc³ÇaŒjIj*UTñŒNÇóƠp>"Ơ˜V¹kŒÇQrtaäơ‡üŸÍẾ—Q àd,ɹ±¼uîæ‡¹|›--Ö"1³^ŸJ½Ḅ̣R£̀‰*z¢¶&vƒ:ÍN¥µ°{X5gSæ\óUäo«.Nb\à³̃ endstream endobj 615 0 obj << /Length 168 /Filter /FlateDecode >> stream xڕʱ Â0à+…[|ï LBªƠI῭ èä Nêè èjúh}Á±ƒx&A… Üÿ—ơ»ĂIÊƯfz9mPk—¥₫°ÙcaP,IkS×¢03:Ï;Å|L EI+Er¦$€ä éÍÑ4ßø.ơ/­₫æ æú@'PE ‚ơ\b<<÷I ya™9PñûpbpO)T< endstream endobj 616 0 obj << /Length 159 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0b#S3…C®B.cS ßÄI$çr9yré‡+›ré{E¹ô=}JJS¹ôœ ¹ô]¢  b¹<]êÿ``øÿÿQ"˜?à ØÁÄ?˜8€ƒ 8{0Á€ƒ¨u¸ˆ â‚Lü€ơÿÿÿ?Äÿ ` .WO®@.̉R_^ endstream endobj 617 0 obj << /Length 177 /Filter /FlateDecode >> stream xÚ}ʱ Â0€áJ‡Â-}…{ÓB(u*Ô ftr'utPt+¦–Gé#t¬<¯¦â –üpw‘Éx’b„1?™¢ŒpĂ dÂsÔƯaw„\X£L@̀y B-đr¾@äË)Æ ÜđÏ-¨=/4¡ñmVgu𤆀èN-÷ñ.‘ơ»µơ´Ñ¦ôt¥+.ûôÆJf{mß?FN3Äwê!c¾t›1²ưÖ]a¦`/B…‘' endstream endobj 618 0 obj << /Length 190 /Filter /FlateDecode >> stream xÚmÏ1 ÂP à·,ÁœÀ÷jE§B­`A'qRGE×>Ö£<€;”ÆôµB‡|?Ns̉4“2!MgohéuÛ¶ƒÓăƠL€j-)ªtCûó‚*̃.ÉG•ĐÁ'}Ä4!ˆrđ8çFüæJüp-27½s̃Œ¬X;+ˆÄ̉YôJ>É!ûùPöDơ°hxƠ°#±qÊ©e¯å̉Ê#\Y.D₫·›â*Å~¹́ps endstream endobj 619 0 obj << /Length 217 /Filter /FlateDecode >> stream xÚeÎ=nĂ0 †áÏ𠀋 ^ •Ơù™ä¨‡íÔ!È”t́Đ"YkMGÑ4z0ÂR :]̃"ħ™=,\ó‚'›7O>i:×aÍÍăưåøAë–ÜOçätL®}æó×åÜúeĂÜ–÷ëµ[V($FFÀÊUG"@'̉C‚„âª;åMBM„IU (“í5«[€rĐĂ÷ßè·eúsKüMô²½§SC¯éĐ©AÏgC4j́ FåV"jÈÆ"k‘ñJh×̉+ừbo endstream endobj 620 0 obj << /Length 247 /Filter /FlateDecode >> stream xÚuĐ¿NĂ0đ/ê`é–<‚ïJUe²TD$˜02´‚µî›ÑGÉ#dô|œ­¶ÊP,ë'Ëç?ŸƯ.®n–\ó¼áùuÍí’ÛßÚP›¦k^œkoŸ´ê¨zÖETƯkªî¿¶ßT­o¹¡jÍ/ ׯԭ€ € 6~ô²‡ÿ9À‹HŸà$Ø€Bz“ÜÏF…ª{bƯa²ĂIŸu=L®₫’1;¢> stream xÚuÎ=NÄ0à‰\D&Gđ\’e£ˆHH––E"T+* ¤Akç&\ÅGñRº°<ŒÙe´ÍW¼ùÑë‡óñ’:è́¢£~ ¾£—¾ăz”Ṭ¿Ñón&li=b{+9¶Ó}~|½b»¹¿¦¶[Ú­¨{ÂiKÆ_AÅ‹…“ÍÙ‚a¶À̀¹âà²bĐYehR¡NÍ*éPđ‚™÷TÑ€à ö€¹„å?ơ‘&ä:È™ ̣Å73ẂMṔuỐiåë‚b₫ö³Á%AÀ/pW°'0eƒ¥q{"̃Lø€?I‚÷ endstream endobj 622 0 obj << /Length 184 /Filter /FlateDecode >> stream xÚ}Í= Â0à” …·ô¾˜kÑI῭ èä Nêè èÜ­àEz„bŸIJ¥Sïƒ÷›$.(qfc.1‘xáIjsŸºÆå™qÄ$±µUj‡¯çû"Û¯1‘ă)Fy•#³¯¨̉œN&"’Yy 2œ¾ä$úPË5s£ÎƠÖÊ®TzƯ)̃zÍ@=°q†ơ˜Qg5椳ü[Ùo¨× Ô}6 đdùcq endstream endobj 623 0 obj << /Length 222 /Filter /FlateDecode >> stream xÚm=NÄ0…_äẨ4{2ÇlX…Ể²H¤@‚j D” (¼GËQr—.L†±(  ù4ó̃ü¼~sr>pÇ>öÜŸqïùÑÓ ­«Øqúă<<Óv$·çơ@îJeră5¿½¾?‘Û̃\°'·ă;ÏƯ=;b`dùD+R*b…(™ÚbØb2L± M¶ó?H@2ĐKĐˆh)¢jĐKXƠ^Eµ¬̀j…U:̉ùÔª•Ă/`rœ`Sœu8&]‹iÖx2U¾D”6ưöaơ]tKßåqü endstream endobj 624 0 obj << /Length 187 /Filter /FlateDecode >> stream xÚuϽ‚@ đ^Hºđô.€Á‰1ñŒ“::htGᵇ“ ÷K®ÿ6i£éd–P@ 5EÅ5^0Œ¥P¬ßÉጙAKaŒ₫RÊè›Ư®÷úÙzṆÏi§)Ø£É F8ơ/nOơŸ‚™+y\Ñ–̉—Â…å1DgiP-¸ đỂ–>Ơê™an,O»´œ”Êzà±½Rê¸0¸ÁÊ^À endstream endobj 625 0 obj << /Length 187 /Filter /FlateDecode >> stream xÚeÎ=‚@à!$Ópæº? b"…‰VÆJ--4Úº{4¶¤ Œ»ÄFi¾âͼÉ$é²È)¤œ%)Å]"¼cœ™0¤ä;9ß°jP(ÎPlLŒ¢Ù̉óñº¢¨v+PÔtŒ(> stream xÚM̀1 Â@…á'Â4Á9›Ä(¦I F0… •…X©¥…¢]09ZâR¦ÖY7Àî3»ü₫l̀Ùas§.O>¹t%ß“Ù1£y8^(NIíØ÷H­dK*]óưö8“7 vI%¼wÙ9Pp®‹HZ¹.µ.¿ÊXÚM®!ú/Ø3(ѯ‡z?Gh ź1đ³n•_ÀÛ*U ³Jø¯„§UÂ@h ;0"« cd­:0†&IË”¶ôºdU~ endstream endobj 627 0 obj << /Length 204 /Filter /FlateDecode >> stream xÚ]Í=Qà+Inó–à®À›áù«$~SH¨¢B© tˆB9;0f¶0;0åâ¹A¦¸_rÎ)®*çkU²©ÂW*P±Fç¨gÛD3ŒgØpQH)”nQº]Z.VS”^“”-:dĐmÑV{9muÈjÖuü–ûºéÍ*<€5¤M̉fâ´ÙˆƯ¼Ôo­ÄîϽö=öf<\?ÿüôlàŸ¬@/âôơụ̈!ö₫g"b£Åf#~Øv±Oå«hr endstream endobj 628 0 obj << /Length 206 /Filter /FlateDecode >> stream xÚmͱ‚0à# $·đ½'°ĐÈ" b"ƒ‰NÆI4º)̣h< бZ{upФư’»ëưMGƒlL%ö¦%ícÆ4Ïg³ WøöfY endstream endobj 629 0 obj << /Length 232 /Filter /FlateDecode >> stream xÚMαnÂ0à³2 Ư’Gà^€:†DS‰‚D$:u@LÀÈĐª•:D…GË£đ=D1>‡$–NßđÛ₫}q̣2ŸQDcMMætRø…1§%íÑñ‚Ë å'Å3”›£̀¶ôóư{F¹Ü½“B¹¢½¢è€Ù„©ÁÔ‚ÇÆ4ºáÄå5„„70„̃Ôz­º³e«(mÖi_ƒĐ,h[Üi‹[«”ÍsÏ?v¡%ûê|»÷ Ï›'ô¦¹§îå½a°ÿ¼7˜3äâÊUVW¾hŒ³vV́ƠÛ©ù×~àr k endstream endobj 630 0 obj << /Length 179 /Filter /FlateDecode >> stream xÚmÎ; Â@€áY¶L“#8'p“à+U F0… •…X©¥…¢­Ù›éQr„”)$ă¬ˆkñ ́?Ś`ÔO'QÉD4Ó>Æ&)¹"Ï÷fwļD³¦$E3—Œ¦\Đå|= É—SÑ´‰)ÚbY€¶Á üè‰LTÅ´³UB3Kºƒî2Pmr/*qû£OŸrZŸv_àÔ¾°₫~½bn˜¹ưåÎJ\á Æü\T endstream endobj 631 0 obj << /Length 244 /Filter /FlateDecode >> stream xÚ]ÁNĂ0 @qˆäK?¡₫̉jƯ`§Jc“è N'Æq̉@p%ư´~J>¡ÇªÛˆa)OưœDiV—ëkªh)«YỌ́ö5¾a³}¥[m¼pÓax¤fáVªº;úxÿ|Ű¹¿¡Ă–jª±Û€?D˃yp̀“”™g€‚YÚǻY”ÜC;@́!‚&_̉@„b•“Ë”?§Ơ³Góá‡efo¯ÈTèö8g¼˜•~²Ñц’év@´Q6Ñtozazkz4‘Utü_)³’ΔQÇMªE¶¬ÿÿóјw>à7è¼x@ endstream endobj 539 0 obj << /Type /ObjStm /N 100 /First 913 /Length 3377 /Filter /FlateDecode >> stream xÚ½[]o·}¿¿‚íCx93äŒqR·̉ÂHôCĐƒj+‰ÑD dHÿ}ÏáƯƯ{-Ù×JºXHw—ạ̈cvfxf†äæf!…ÜrSÜKP/¸{°^q¯¡Ÿ·à.¸÷P{¹§ĐÏ»I¥#¡A¤Ë.wcO¬‚.sa¤ A!Qƒ´Â:-HÇX¹÷ hJJAµ(Ô@NI´HÛ•d¤-¡$­ »$PÛÅ‘¹)³r &D§̀;́Á²!!)X©èY$XEE4X³º+bx[gĐ$¹x Æ: Î ̃„d‚”ƯØ^»:Jáu‹ ÉEeåcO»‚·-ÚyÁ㬠UAe) dü+lĐØBQÚËh<-d½+,&Áï=7Ù«”*ESÀZđÇ+‰Ư^É H̉Ç1 U2ăWµ¢N–PsD…Z u2긃Ï9‡Ú+›o=´ä+×Ф³r Í@fÉ=´ Í( ®2¡Hh•ï)¶æè¯Ôz·]È»R >dèîÖY§†>ø‡̉îd´ªW*ºèLp*["Àuˆ©¡:¨Â‹ :‡$e_<3Ơµ̀²âäkBªA— UAàĐYk,C/âh¡hT¶Pm¥™8SÖPq¡°hǧÅ‚œ*å.‹’# ˆ‚¦ƒ‰yb ZѸ —‚ׇ˜ É̉ÓîÙ³Ư₫Ûÿ₫|öŸƯÜÜ̃ïößụ̈ïû‘ÿêÍÍvûç·w¯¯ï.fmºÜÿeÿå₫ó ™Ư₫ëëW÷á¤Æ1r³è˜Ø<:'[‰˜y¨öYxö,́¿ û?ß~{ö_„?ü|ơưuỘÇđé§;üÿÿ4h*1A;sMQÀ•;gW“Øs;CD]‘ˆªÑ1‹Ç‚ÙDêPö­÷34ô5ihèØa1A€W¢rlùmE"¼Æ„ÉÚ#¡\k%ÚF$hœ¶Ñ+„‘SŒnk¬­m¤•Öb36svå0SRj}"¤÷hà€AU95Z°ê)úF4¨`¬̀= …¡ ×Vk mćÖ"m­̀RMl˜9ˆé²±0¬Ç!,Â()¦¬[IĂ1×0¨f6üLS§eæ@lÛˆˆi‚ àǹÔTØy+ÀÄ„­7"m|NÁ]SH)Ûiø$Hu4hl•ø \¡(g´RVÅkà2]qnĂƠ‡‚h~é>Ȫ 7†É&VTxej%BS¡M=£•R×7Ÿp:£A#fó© àQó6œ‡Í‚ŸŒ(&K@T££XAŒle@^éC¡,DcexZåĂD´ơJ¤Eúè3P‰+ü #̣ú Çö#/ ·`áÛ¸– cB4è@ /#D¤VcNçf§¯I@Æ,D —† VÈ }A[9£“+Î +t¨½B"ÀLZî$¤)aämh€Sß–×+Hè-"ÓufNè’€3™Ôæ:PÎdño‡jl¤0”¡?ಠ́-Œ¦3¼T·A¨Y%ÆGFÔ6Œ8W̃eÛHirµívº3ˆ³¬reÑïVÂ(¼3WÑ\.BÇjY<ëØ®(ŒŒ‰P³McsÙJ4Áv™Ë6Ö{î•ñÆ$ŒŒ¸K}#®=ŒVVhă æ)œ«*y§̉ yGà™a«ï Œà ^¦÷¼áœ0½(Hxg‚ơ¹Ù¹æÄ"d§¡€Í•5]Ÿvæơ'†1ö¯Ç‰ññ°sE}ÈàKëñe3x’ù _[Ÿø×±4=‘`Î{Ùˆ̀FéŒøàÆq!˜‰(øỰF.嬗 ¯[!“^*|*í¾­Jh¶ûÍ̉P8Yˆx62á“/3;ú³/£ˆ‚·2\phoă6–æà`7²E€˜e#uÀXpùáM†cÏí˜Ă ƠVÑ!ÿijÂƠû’c7ĐU-º‘#Ó$6îo8Ô‚›|pđ¸ÉQ –Ô6¢!sµ¾qgª "¸6ÂÀĂ¹XK×7S‘Ûb1D đ`O¥á‹pQ¬ ă¯Ă₫ÿüW€\™¯đ1Ón~ùñÇËUbÜçn|¤̣po ¢Ñ¹§ùNƯ·7÷ƒÖx;´zQR Ô2Ü .>2hµywûê›kp!́_~ñ"́¿½₫ơ>\¾ËØ—xÛƯ₫st~}sÿ6Íɾ··¿Ü½º~;öäFÑ_¯_¿¹z~ûk /@yE,ßà 6®}¿¼ºCÜ¢9T"{‹Á¹…I’¸ƒy¸Ët×é>?ÏÓ½LwŸîuº·é̃÷2ơW¦₫ÊÔ_™ú+Seêob 7,÷©¿2ơçS>ơçS~èïr¥E 3i¡&ú¶˜Ÿ,0O+lHëçf…¬¿Hé,Ë"eM5Z>7-̉‹Aœˆ5N>J(—æ²1#̣đ¯g> ö'Z~˜K«ouº W©—­N{¤åh@ÜÏ]E.>èX´ª‰Üαâv+1̃ƒĂo±±ơ~`¦:ü™ÔÊ&+RJÇ+R=åk02Vêó&mE" ‹Œ¼ C«J/²–AüơV7"®k¥Áäzˆóô93Î¥€¸²‰B̀[ß°\«_¶¾÷¸Ÿ‘†Øú3£(l3·· 6¬ŒÁ·©u£M¥Y/…«´eÑË¢$æ}}•ÈÜÑ`©7øR‡(\kۨƾM§·bă~cÏÎÓm5VßH'¶:ó |ëœèMÖ±<•i>¤n²,5á¶b9= “Pܶq®§ưV®„¥ªË~+Ăß²NÍgtîp§–3:ѹưœUi˜¦@ë™ø8—uÈ›,Ï çƒr=pÅă›'TÚØ[ê¥o„•`[i1ÉŸ›Ë¸çÖW›™¨ 0ƯïzàC.p¯Û6Çæƒ)’0‡øcØ9̃V?%ÄơÁ4*5À$Ô#QUŸJĂSZØ{ŒN ă}]):e·'oÏBÛíÿvơŸ¡çĂÀ½º¿{ð”Ë,ÆđwL_j=¡+ >á]¡ —§q.©HÓ—?)ÏĂå øÅ›»·÷ŸÿpurÙí¿º2¢²ÛÿưÍëû̃³ª#øưÓÍ«Û×on¾gVG ë²û·ăđ*‹ĐçàºÊà'ưÖ?¤—¼›₫øk~è₫é̀“cëËñÎ\‚ª½ùî»ë»ë â"—ư÷»|¡ư¯¯¿ ^÷WX -%UöWă‡ĐÙ¥‡†.%-í¯Z M% íØª£wL~́½w”tY^àoí¯ètỈ“Bc!2ç“ÂÂBøÉO  Ç‹$^Ø¥Œ£̀Ç’Y8.́Gœ—qpăXGÙPe™-WăÈø´đBNïS†'Æk3đ¦«̀x±U§ xTªÍV›V}È™RËœávư´D4¸(eÉ1fiKƠ¾äJ´´ä¸Ï?“Vđư’CŸÍ–(iyÉÁoeÉ1&Zhá·m¡Ex´a¡…Ûé­'#¼¿|:̀Èc˜Éƒ῭Léwa†ßđX}®3̀,(S¡Œ?F™º¼0Å}Ă'O½wơªç¹£§r,•G™ù%̣˜[ŸP™‘^@¬ù{ÙeöTæ9ÿwùåfùŃÿ3¿àÀơö^¬<<9½>,}*’Ÿoó₫̣¹ôôécrưư-Ï_Ÿ bÈûí˜`7~T>Ä4Gô΀J₫øáˆ|û߃ë¨óÛxƯ1v·Đó́ǯ܈Mi/:@—üÛ{ó€8?+I3HfÆ1ÓĐÓ `‘§/Ç'+s°ÉMÀï)ßS9»§8ùSŸ‘’Ÿ;ơ~~~ó2e¿k:ZOGlǨ’Nl‚Ë‚í ÓEO,„Ë‚í‰ëùÄ^¸”{áâ'ö崯 —vb/\ú‰½p]h́“ëáª'ÖĂƠN¬‡k>±®G;Zôhg:O .–…_yÚ×£©<Ê…(ˆ×CßÈ=L=å §Ñä·5{B§ặ₫̉y¼cÉIåc̃yê|º¾·ªÖ2Ơ<ØƯ —ƒ8•ªæ<ÓüPÿéÈ bß[Ôïƒ@<Ÿó£Ë‹Ÿ5 hăi^PŸ}Ï/6¾8›î¬7—3Íß\^§¶§?ö9÷?÷A3ÏÛ_<¬ư±Ÿ¾OSĐüôp¸–†̣7‰6¥ïX§#̣T‘N×I!€'£‘,uÜ Álá!ûP[uÔ3§ü¹@Ù§ÖœA]|z>•¶SïælQJô¹ÖcȘt¾̀ v|Ñ‘¢1"˜Ôb¨óTId³hNƠhÔ­íĐnª·´›̉}å\>«ĂP ~jÊơ6ªÄ¤f³̣Ú鱑¢Ó‡±:Æ_Ú̀*:©ẳB>ªÛåîp(H endstream endobj 641 0 obj << /Length 197 /Filter /FlateDecode >> stream xÚ± ‚`…4wéº/Pj–)‚äÔÔMƠØPÔ>â#46È_Gth ¾å̃Ë=監(TW½©Cơ# |=yr•±Ï­«3¯;/’fất́‹³â^œl­÷Ûă,Nº™+ç…î=u’-ˆ',ƒ]£ÿÆ BR"/đ ¬½wƒư‚]¡OJ HÑ4äMJ‡êÿ0?_9º¨¤èÂÙÂ.6²—í­†Ơ¾Ñ†ô¤-iN«Í‹e™ÉV¾‘L endstream endobj 642 0 obj << /Length 196 /Filter /FlateDecode >> stream xÚ= Â@…Ÿ¤¦Éœ èæGb¬à‚Vb¥–‚•ñh%GH™"¨/ÙÂVøẽûf˜ Æ©j?Ơ8̉$ÖC(g‰b…îg’©³Ñ(³àXŒ]êơr;™®fÊw¦ÛPƒØLï@ |Èù “~‰n¯Fç ˜<z/ø¤@—”đ:ºMrpíñïß\3]8[ØÅFö²ƯiäÍƯhHOÚ̉™æôÿ´A¼HæVỌ̈xuO’ endstream endobj 643 0 obj << /Length 110 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0´TеP01Q03VH1ä*ä22(˜B¥’s¹œ<¹ôĂŒL¸ô=€â\ú¾ %E¥©\úNÎ @¾‹B´¡‚A,—§‹BưÿÿQÀ¿? C ưGơĐG\®\\0ñoy endstream endobj 644 0 obj << /Length 112 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0VеP0²P03VH1ä*ä22 (˜Bd’s¹œ<¹ôĂŒL¸ô=€Â\ú¾ %E¥©\úNÎ @¾‹B´¡‚A,—§‹Bưÿÿ‘@ưÿÿ öC Ơÿÿê…\®\\¼HB€ endstream endobj 645 0 obj << /Length 106 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0UеT01RĐ5RH1ä*ä26 (˜C$’s¹œ<¹ôĂŒÍ¸ô=̀¹ô=}JJS¹ôœ ¹ô]¢  b¹<]êÿÿÿÿLñÿ!ÁåêÉÈW51ñ endstream endobj 646 0 obj << /Length 118 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0V0W01Q0±PH1ä*ä21PAC°Dr.—“'—~¸‚‰—¾P”KßÓW¡¤¨4•Kß)ÀYÈwQˆ6T0ˆạ̊tQ``°a‚:ªöÿÿÿÿS$₫ưG`1jÛ%€₫àrơä äÀ¹> endstream endobj 647 0 obj << /Length 142 /Filter /FlateDecode >> stream xÚ31Ó³´P0P04SĐ54V06R04TH1ä*ä24 (™Àä’s¹œ<¹ôĂ M¹ô=€\ú¾ %E¥©\úNÎ †\ú. ц ±\. ́ø?Èÿ°ÿaÿÿÙÿ“ÿÇÿưCĂ?†?Œ@Èüƒÿƒư‡ÿ₫øßPÇ`ÁÀåêÉÈÑ4,r endstream endobj 648 0 obj << /Length 96 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0Æ@ÚP!Å« H(€¹`™ä\.'O.ưp —¾˜ôôU()*Må̉w pṾ]¢zb¹<]ä́êüƒớä¸\=¹¹– endstream endobj 649 0 obj << /Length 162 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0UеP01R03VH1ä*ä26 (˜Bd’s¹œ<¹ôĂŒÍ¸ô=€Â\ú¾ %E¥©\úNÎ @¾‹B´¡‚A,—§‹<bÆ@‚N°ƒ ?˜8$äÁD° ­ơ ¢Dü`#˜ø2î©fâ2˜X3Iq,63© ă*@—«'W yK/ endstream endobj 650 0 obj << /Length 157 /Filter /FlateDecode >> stream xÚ…‹±‚0EkH̃̉Oèư-„ÀD‚˜ØÁD'ă¤]‰ŸÖOá:2b˜½g»'g•/Ë18Ç‚S¤ ̉W¦qîY2¹ËjCúÎHoƒ mvx=ß7̉ơ~ &ƯàĈÏdDVvÊUư„r²‹¬ø»Đ9ơ+†€¯¼̣̉G^´Â‹a˜÷̉UńF;~ZQÚ:Đ?¸8 endstream endobj 651 0 obj << /Length 102 /Filter /FlateDecode >> stream xÚ31Ó³´P0P°P04W0¶T02VH1ä*ä26PA3ˆDr.—“'—~¸‚±—¾‡‚—¾§¯BIQi*—¾S€³‚!—¾‹B´¡‚A,—§‹Bưÿÿ?₫ÿÿÿƒÄ¸\=¹¹E:(“ endstream endobj 652 0 obj << /Length 118 /Filter /FlateDecode >> stream xÚ31Ó³´P0P04P0"sSs…C®B.#3 ¨‚‘9T*9—ËÉ“K?\ÁÈŒKß(Î¥ïé«PRTÊ¥ïà¬`È¥ï¢m¨`Ëåé¢`ĂÀÏPÇ ßđŸÁ₫!\Ï`߀ ƒ̀À‡Aöp¹zrr]7½ endstream endobj 653 0 obj << /Length 190 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0bSSs…C®B.ßÄ1’s¹œ<¹ôĂLŒ¸ô=€¢\ú¾ %E¥©\úNÎ †\ú. ц ±\. ö P߀ ÿÀJ2~~€‡d₫ü|"Ù₫ÀN‘ü₫`%åê°’ö ơ ́hL²¨ FÖÿÿ'ÿÿy“ü´ñû,$3üÀÀŒêÿ3Øÿo€ÿAŒYœËƠ“+ H0‚6 endstream endobj 654 0 obj << /Length 198 /Filter /FlateDecode >> stream xÚ}ϱ Â0à” …[|„̃˜TkÑI῭ èä Nêè èj}´>J¡c†̉˜ 4è „|4ùÓ;.ˇ³)J¹q’ă)…+di¹#Ç  Ä3 bånA¨5̃o3ˆb³ÀD‰ûåT‰•µYk[Âz^Dí«yĂ’Æ1 ¸é‰<­ƒư§QøƒS˜H¨hUsjD0NÍû/ëưỢ£QG<ó¿Tá]×ăKÅDbh@C£6„“3K[x£Gœj endstream endobj 655 0 obj << /Length 230 /Filter /FlateDecode >> stream xÚ¥Đ±JÄ@Æñ/¤L³°óº Éi¬ç ¦´²+µ´P®Û©¸©ysÎϽQ­‡%oÚơæé•¶=¹{®[r×é˜\ĂïŸ/ä¶·—\‘ÛñCÅå#ơ;üĐ"ÓL EĐÅ(đJ£däG)‚2£3!_±#2±C¢[°â•Ă{GE₫Ạ́Àá{ÿûåʰ :Z2 fF…€bÖ˜9eÙ)úQSFÊO?˜V2C—ºêé¾?9ru endstream endobj 656 0 obj << /Length 197 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0bS3…C®B.C ßÄI$çr9yré‡+˜ré{E¹ô=}JJS¹ôœ€¢. Ñ@-±\. ơÿÿ700üÿÿÿ˜ü&ÿÉÿ @Y 4ûÆÿ€$ƒư)&ù?€Hö ’L2₫A ÿÈ:0Y&íq‘ Rbb¦ùơH.©C¸ ÙÍ_@|ñü¸¯A! HÈÀCé,ô !ÉåêÉÈƯˆI endstream endobj 657 0 obj << /Length 149 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0bSS3…C®B.C ßÄI$çr9yré‡+˜ré{E¹ô=}JJS¹ôœ€¢. Ñ@-±\. ơÿÿÿÿĂ$₫ÿĂBÖƒIæ uD“6`’ùD2₫ÀJ₫ÿO˜Ä¥j2ÛøÁ¤|©$(4₫7üÇA‚e¸\=¹¹WD–Ü endstream endobj 658 0 obj << /Length 141 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0bS3…C®B.rAɹ\N\úá &\ú@Q.}O_…’¢̉T.}§gC.}…hCƒX.O…úÿÿÿÿû€$₫3``°'LÈ|DˆøƒAüÿÀ¦jåDưÿ ÿÿÀ À\®\\,˜µ endstream endobj 659 0 obj << /Length 230 /Filter /FlateDecode >> stream xÚ•½NĂ0€/Êé?Bî¨Ơ…vÔ©`b@LбÖ̃ ̃$R_à¤.•åjŸKÅ-}ƒo¸ï³»ͦTĐ˜®Jr&7ôRâ+º‚ÂLăäy‹óí¹íÚ?£­oéưícƒv~· í’K*°^ÀḍĂ`dÏPÉ‘¡aD¾„ÓZN{¨8;@Ά:0œGdœzT €”Û 3’Î#̣́§ÿ'dè!Q M„4·ẹ́³† ưú™¨«â>¡1¥£5ßÈĂ—t*Œ«ïñïć5 endstream endobj 660 0 obj << /Length 114 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0bSS3…C®B.ßÄ1’s¹œ<¹ôĂLŒ¸ô=€¢\ú¾ %E¥©\úNÎ †\ú. ц ±\. ơÿàèÿÿp„,Îü~èÿÿÿÉBÄ„—«'W NÁ§P endstream endobj 661 0 obj << /Length 105 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0bS3…C®B.c# ̀I$çr9yré‡+qé{E¹ô=}JJS¹ôœ ¹ô]¢  b¹<]êÿÿÿ÷ €ÄØ0 %ŒË\®\\6Qg? endstream endobj 662 0 obj << /Length 231 /Filter /FlateDecode >> stream xÚ]ϱnÂ0`£ ‘nÉ#ä' v ¨D$:1 N…±Clˆđf1t́#4ÑCd÷?Ka@–?Ù>Ù₫ÏŒú¯/œñÓx›Ó7™Œe`+…Ï/¤×l2̉ œ’.–|Øw¤§«ç¤ç¼É9û bÎe«ÊÖ;U:à”.âJ¥•p΂ZĐ³ j@¨ARô&ÎB n î²ú~àÁßx¹ëàä)É[yÙF ‘ßê^Ó}®l—Eùƪ‹‚é#Ô ªÑ`"­¦₫‰P ·‚̃é0Đ~? endstream endobj 663 0 obj << /Length 126 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0bS3…C®B.rAɹ\N\úá &\ú@Q.}O_…’¢̉T.}§gC.}…hCƒX.O…úÿêÿÿ``ø'ê!P‚È:„ˆ°'–¨ÿ`àbÿ¸\=¹¹”…jo endstream endobj 664 0 obj << /Length 201 /Filter /FlateDecode >> stream xÚ­Đ1 Â@Đ‹À4¹Î \kP1‚)­,ÄJ--!9™D,,½î¶T×]…S[̀ƒù3Ơçn¥Q§*9z¸K5—¦.s½WÍj“9ú!²!q¬«SdaVËơ ™ßo“ƒ, ‘₫cP$”ˆnPPB¥z@QÉÈ(>Z°öđălíl/5.§ẩ×ÄK=&M£Ø¥ÄÆ(o9)÷Œ[‘·•ä-Ç_m0ÂÍv¢`é®̃fś„8À„‰‰ endstream endobj 665 0 obj << /Length 199 /Filter /FlateDecode >> stream xÚeÈ1 Â0Æñá-ÁwÓ–ZtP¡*ØAĐÉAœÔÑAQPPRo¦7iqpT· ¥±I( 8¼ïû{~£ƯBƯâ¼&6}\9°Ol[Lñ,7„@gè¹@GEq¿;¬“>:@8wĐ^@8@–’X&äaüÆs!Ëe—V^Äz“̉Hø4½ ¦±6Q¾µ±25> stream xÚÍ=‚@…ÇXLĂ˜ è²̣#V› &na¢•…±RK ¶ÂÑö(̉‚°.CÇ l¾â½æ}/N竌BJh&)^P²¤«ÄF© ]œ Íå¹Fq¤(E±u1 ½£×ó}C‘ï×$Qt’QʘZÛ‚gm¾µ‡J9Ơ€ƒeÊ ‚ºđë€7FçĐ´Ó?oaŒF̣ú½ k©ïÄ öª,Íú|_ÂçàFă&h endstream endobj 667 0 obj << /Length 182 /Filter /FlateDecode >> stream xڭϱ Â0àHá^Â{ÓŹZ+˜AĐÉAœÔÑAÑƠöÑú(}„$ç] 8Nù ¹ä¿KMó9&èx¥g,\Áå¼Od+…ă f‡.³âS0~÷Ûă ¦Ø,Đ‚)qo19€/±"jơB¨.P«;UùD÷ŒF¯ Âó'a¸üy£bhŒçF±¥4j-iMËđO*ªÿ·ù"`éa oơÆ…t endstream endobj 668 0 obj << /Length 218 /Filter /FlateDecode >> stream xÚĐ½ 1 àÈ Y|óÚ;©‹‚?à ‚Nâ¤Îç£ø"®äb/YÄÁÁ>JÚ¤¡¶Ưèu)¢&Ơc²jµiă­ơɈZ=Ù́q˜ Y’µh¦>&™Ñéx̃¡ÎG£Ó*¦hɘR. eΘى/É".à‹̉¬t Ọ̈̉ªª®ôwèđ£VûhOé/oé»2C óxŸûB§©’ÙbM•nƠÿ¼æ¥7÷íƯ¥| "ç₫ĂÔ€3Ÿ©ˆàĂ¯>à$Á¾$J endstream endobj 669 0 obj << /Length 250 /Filter /FlateDecode >> stream xÚu1NĂ@E'rai=ÂÎÀ1IL¨,… á ªˆ¤DöѶă¹.·₫ü ‘(öigöÿ?³Óêølnc›ÙQiÓ›ÚºÔ'Tl²=ÿy¹ĐE£ÅÊ&•—lkÑ\ÙËóëF‹Åơ¹•Z,í¶´ñ6K³NZäa|„ ø 9€à|t5»¡î¡iĂ»H†„ˆÿ…û J̣bz<„„ë¼rd'¾¥0Ơ´ †½(9qp&8 %? cF¿ûi=¶H^†Qèù #tü)„g/pxLkDÏ…3zô¢ÑưA endstream endobj 670 0 obj << /Length 127 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0bSS3…C®B.ßÄ1’s¹œ<¹ôĂLŒ¸ô=€¢\ú¾ %E¥©\úNÎ †\ú. ц ±\. ơÿ Dü?€‹üĂ`ÏÀOY$Ù€$ ;R₫ÿ?óÿ¬$X–ËƠ“+ V—Xê endstream endobj 671 0 obj << /Length 174 /Filter /FlateDecode >> stream xÚƯÊ1 Â@…á )Óä™ èfaµ Än!he!Vji¡h-GɶL2†€à „á+₫7&.擦‰&“R’̉Yă ‘S2–Ós‹jOÆ ZKFe7ô¸?/¨̣í’4ª‚â#Ú‚J®"n˜ëŒƯ¯Ăê;€₫ʼQ¯ưºO„7ZB؈U$fMYD̀@È ÷¢Ḯ̃f̣‚+‹;|WWŒ endstream endobj 672 0 obj << /Length 197 /Filter /FlateDecode >> stream xÚ}ÎÁ ‚@àÂ\|çjUÔê$˜A‚:uˆNƠ±CQWơÑöQô /¤mU²%vøÿ?,ăÓÅœlriâç“ĐÙÁz® ṃgCsºb” Û“ç"[ËY²¡ÇưyAm—ä ‹éà}Ä$¦́–ÈE'Â}2´FZ_V 7 W?ÓWăei f åßÊÿ¥)X¹ÊP>•V*5y«ÔàMg9V/«Îz¬VJAđf9ô'à*Á¾LCx8 endstream endobj 673 0 obj << /Length 210 /Filter /FlateDecode >> stream xÚϱjÂ@Çñ_p₫K̃Àû¿@{98Sj@-4ƒ “ƒ8µ •¶ä-rpn‘âA0fẸ̀¾¿é§ăÇá€#Vü XÇÜù]Ñ–´ö1â₫ÓeyÛĐ8%¹d­I¾úL2ñ~÷ùAr<Ÿ°"9å•âhM锳AiËtJwïeB# LX‰6vs`ÔRaFèØ$ÿi4³•‡÷ ;¹¢QWytExƯ­'{¸úgk~ç϶É,O*¨™á$½=t è%¥~©–§ endstream endobj 674 0 obj << /Length 242 /Filter /FlateDecode >> stream xÚmбnÂ@ P#$/ù„ø ¸…¨"•©L ˆ :vhƠ®ÉñgáO@ü@$2D¸v."PtOñùâ³Åă× h"+̉4¦}ˆßih¨/»/œ¥hÖMĐ¼Ë.tI¿?Ÿhfs Ñ,hR°ÅtA ×đï÷LZ5;¨Á·: —GÍÄÄ̃kÑ?ª̃±R/êèRª7ux;©¬¸xl;µđ3{gúߺjmåkÙƯx®ºN®|סëÖũ”Ή²v:Tæ-tjO¬À;Á°‚Q ¹dÙæ,¿Å²Z8ƯËâ[+üRô endstream endobj 675 0 obj << /Length 201 /Filter /FlateDecode >> stream xڵͽ Â0đ+ ·ôzO`Z©E§‚`A'qRGE×6–G©o ¸t(Æ;…TÜ%—wÿ.Íz£!ÅÔç›hÑ>Á¦2Ç2J³;â¸@µ¦´jÎ)ªbA—óơ€j¼œP‚jJ›„â-SªYmEc-äÎẉy îà7RŸ†ơؼ€5ü“-!̉äl·Ơé²Ó<ÙĐ´âM nÓÜ̃£­ÖtVúWYơwÛ8CÛ:¿rœ¸Â½bÅ endstream endobj 676 0 obj << /Length 186 /Filter /FlateDecode >> stream xÚ­Ï1 Â@…á aàœÀMˆ! L!he!Vji¡(X™Í£ä–)×ykkéÂ|°³üÅ̉₫x$‘ 0‰ S9Ä|æ»W<́O<-Øm$±[Ø–]±”ëåvd7]Í$f—Ë6–hÇE.™÷¾) ưѨƯ—Ñ ÔFïidjBT’̃6-5Ú†RPRB *úszGªH©v–*RÍ–*̉ïưđĐđ¼à5{̣}ư endstream endobj 677 0 obj << /Length 220 /Filter /FlateDecode >> stream xÚu=NÄ@ …_”b%79Âø ƠHË"‘ * D[n‚–™£å&́¶Ü"yămafôY²ŸíyưÅéơ•.ơ\O:í/µïô­“wa\̣ögÇÊëVVƒ´O¬K{Ç´´Ă½~~|m¤]=Ü(³k}fÏ‹ kEÚ¨m&fh̀F ˜í€hÆrĂ¡° +'Ø2¾©ʉ3Ùq4|PYáÂÙØ0eܦÑé½³súŸÉ5ɧ¥\Ó@ÜñïeƯ'ưXæÆÆreSU¤4¹äQ~MQdÅ endstream endobj 678 0 obj << /Length 206 /Filter /FlateDecode >> stream xڥϽ Â0đ+Â->‚÷Z+©S¡*ØAĐÉAœÔÑAѹ}´>±bđ¼$*.b†áBî₫§zíá€:Ô¥VDJQÜ£m„T‘;÷ưËfi†á’T„áTÊf3:Ï; Óùˆ¤:¦•üYc6¦\ƒ®¾›;ƒ¿lhkb¬̀⹄€™/N-êÄZ6*±¨ñp·—§¹ë™|ZX›?¼4®ḯơ½>uóÎæs¾’—n—‚«Ư tńÆÍ N2\àKKv endstream endobj 679 0 obj << /Length 205 /Filter /FlateDecode >> stream xÚ¿n1 ‡]1œä%oĐó ´¹”ˆ̉)$n@¢S‡ Z•µ—¾Y…G¸‘!±i…ÄÖ _¤Ï²ư³=¾Œ©¡gzpäŸÈ;Ú:üÀ¡Ù¨¹T6{œ´hßhèÑ.D£m—ôơyØ¡¬¦äĐÎèƯQ³ÆvF0à`ø80¸cfñ̀±bè¢9)zA}T$"ÜË'¯S|_QùŸ(·½Ưª(ăM I +ëT÷PG“eyÅ?¿Ñ4dѸYƒ÷z‚Ü1…ó_ñ ° S endstream endobj 680 0 obj << /Length 220 /Filter /FlateDecode >> stream xÚĐ; Â@à )„isÁJĐùEü"Ăøb=A×Û çaÄS~]¿ endstream endobj 681 0 obj << /Length 216 /Filter /FlateDecode >> stream xÚu1NÄ0Eÿ*…¥ir„̀À › ¨,-‹D $¨(VT@I‚vă£ù(>–)V¾AĐaYỌØóç¹??½¼ĐV=é´ÿ̃ϼÉz`±Ơ₫́çæéU6£ø]âoX?̃êÇûç‹øÍƯ•vâ·ºë´}”q«¨µE X̀X™Í῭p‹[PÏ0ÔLhB M ‘‡ÀÆ4́‘™æ̣±À¸₫Eâ ŒÆ₫S“«D¸̀iDf( D“œE‹T³HIc %)>—/Đ~Å’\r/_})oG endstream endobj 682 0 obj << /Length 164 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0bSs…C®B.c3 ̀I$çr9yré‡+›qé{E¹ô=}JJS¹ôœ ¹ô]¢  b¹<]ÿ300°ÿ?ÀÀ ÿÿC=ˆøÿÿ„`üÏÿùˆøÁ₫€ưcf ‚¨ÿÿÿÿ?€F€%ˆ5…Æ„ưÿÿ@.ư‡N€%¸\=¹¹CSṭ endstream endobj 683 0 obj << /Length 275 /Filter /FlateDecode >> stream xÚ…=NÄ@ …¥ÉM_̣Ă(‚†‘–E"T+* ¤A·ÚDâ \%7!H9Ec{·BHLñidû=¿ßŸRI'tT×ạ̈%=Vø‚¾–jIM}h=<ăªÅâ|ŕԱh¯éíơư ‹ƠÍUX¬iSQyí ɳă:₫²œ!1¦{.g½‹é́ ›t<A9ÀN¤t¿´É½êà`nê [¢Yè˜'ă(3’@øÉ üˆÊ~sPºo£i5¹ƯE,b”³6ÂyÔ0ɬ1$ÄV¸ ç îÁ˜ÿÁÙº[›́Lzơ #¸̣ºh»&Û;‚₫¡Ä³$²^MR} ^¶x‹?máÊ endstream endobj 684 0 obj << /Length 165 /Filter /FlateDecode >> stream xÚÅɱ Â@ à: Yúæ ¼k¹ µ‚7:9ˆ“utPt¾>Z¥pcÁ̉˜(¸ÔÍÁ@>₫?1ét>C1¯I0I±ŒàFº–*áx†Ü‚Ú¡‰A­ø Ê®ñv½Ÿ@å›F  ÜG¨` t>à¡ö»îåè'C/fH=û b‰¨úè³­'b6l öÁ˜í¶ÿÑQă¨"̣DơĐ÷–¶đi—¶ endstream endobj 685 0 obj << /Length 137 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0bCSs…C®B.cc ßÄI$çr9yré‡+sé{E¹ô=}JJS¹ôœ ¹ô]¢  b¹<]˜øÀù(B¬`ÿ¨­₫ÿ ÂD00 ¢₫ÿÿÿ ÿaDœ€Hp¹zrrȧYA endstream endobj 686 0 obj << /Length 168 /Filter /FlateDecode >> stream xÚƠÏ1‚@Đ!&Ópæº, `E‚˜¸…‰VÆJ--4ÚêÍ£́(-Œă!¶¶₫ä5ÿW? Æ9E”R?Ö”$4̀h§ñˆqÓF”åí´=`iP­(ÎQͤGeæt>]ö¨ÊÅ„4ªÖ¢ | ¸°₫êºfÿ!̀NÔ^ :àÿ^Ă]寸3„¢° l™nüO(øÜôØN .ñ ú‹k7 endstream endobj 687 0 obj << /Length 217 /Filter /FlateDecode >> stream xڭνnÂ0p£H·ä¸'À ¤Q™"• ¦ˆ‰v́P+Ä‹eëkdëÑU‡ÿÇGkÉ?é>í4ë8æ^¸iÆ¿%ôIi?Ä1B–4,ȾrÚ'û²d‹ ¯W›w²Ă鈲c'/¨³kL8âïëTó¶E‚ÑẠ̊ÆkƠä%t:u€­=|đº?ơQ ;D»ñN÷ üd~UôÈ7úå ³²S[Øv0ؼ?½b¶j®vÊ?£ ¶kµ1N\*ïÎÖ7V§*=4£#SăŒ÷ endstream endobj 688 0 obj << /Length 123 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0b#S3…C®B.c3 ßÄI$çr9yré‡+›qé{E¹ô=}JJS¹ôœ ¹ô]¢  b¹<]êÿ``¨ÿÿƒá?œ¨‡ ŒĂ—¨ÿÿÿÿ0Äÿ?€ „—«'W íâg• endstream endobj 689 0 obj << /Length 161 /Filter /FlateDecode >> stream xÚ31Ó³´P0C …C®B.sˆD"9—ËÉ“K?\ÁÄœKß(Ê¥ïé«PRTÊ¥ïà¬`È¥ï¢m¨`Ëåé¢ÀÀøƒñC}ÿ₫? ÿïÿ“ÿÇđÿÿûÿ ̣ÿÿY–o`*á?À₫ƒÿü„Ø!*9 °₫=₫ÿg„ÿÿƠ!Œ‰@d¹\=¹¹ªˆ÷ endstream endobj 690 0 obj << /Length 159 /Filter /FlateDecode >> stream xÚÅÉ1 Â@б¦Éœ¸»a­1‚[ZYˆ•ZZ(Zo¶Gɶ 2΢]àÀ<₫Ÿ±óérArY;#«ébđ6uj ç–Ơlj#WTnKÏÇëªÜ­È ªèhHŸĐUE‹€[îÅ7³(Sÿô‹#“d5"${‹ƯÀö?zn<×̀‘9 ư~qíp%8} endstream endobj 691 0 obj << /Length 198 /Filter /FlateDecode >> stream xÚ1‚@E¿¡ ™†#0Đe‰V$‰&ZY+µ´Đh+{4Â(- ă²˜ØÚ¼âOæÏ›$ͦñ„‡“1'O®§6ŒºÄM¤v§¤V6&U¬ù~{œIÍ7 Ö¤r̃kTä ï dR" "/x"oø­ß"x Aa…̀„¡É,ª ª̉¢~~Ûæ5ÿ¢µÍo×U9ôơú“ö¸qNÈ©9I§‹Rêï Ư3´,hKí`• endstream endobj 692 0 obj << /Length 221 /Filter /FlateDecode >> stream xڭбnÂ0àßb¨t À½@›Y"QÈP‰Nt́@³óhyÁc×s U‡.•đđɺ“Ï¿m˧ç ç<æÇqÎÖ²Íy[Đl¡ƠœË[kóIÓ²w¶e ­SV¿̣₫ëđAÙtùÂZñJ­©10ô€óU¤QÏ"-D×±×ɯ<Œ´ĂNmA…Q/À%n®:˜¨~ÛDGÿ´ºú9ir2Ư˜L¤y?ÙRΘ<ÚÂè[˜S|—é\ˆè³ƯO§÷é¿éOưeể¼¦7úF©W endstream endobj 693 0 obj << /Length 229 /Filter /FlateDecode >> stream xڭϱJAà?lq0Í=ÂÍ ˜ƯÓ%Ä*#xE@+ I-SD´5_,9È ,Ø9nœ½sck‘æc™ùÿơ£áơ˜_ñÅ¥c?fïø¹¤5y¯SÇ£´Z®hZ‘}dïÉ̃éœl5ç·×÷²Óû.ÉÎø©d· jÆ0í rù ÀDªÈWÀ@ä`D$ £æ ¢“€¢F¡]ç67@–üH€¶³ù·ṃtçt9OYªæ»®‰®´Ơẃ–µ±gß¹ïßÿÙ«…èe˜&Ú¥œOM«“&Æÿú7§Ûè`Ÿß endstream endobj 694 0 obj << /Length 172 /Filter /FlateDecode >> stream xÚµÎ1 A ĐÔi¼“832ˆVº‚SZYˆ•ZZ(ZÏXYzâÅ#l¹…l̀ÛXZäÁOø7è†d¨/ă9C;‹GtV²ibsØ0ó¨Wä,ê™lQû9O—=êl1!Ùæ´–Ê}NĐ)!0„Z¼2ó-ygÉg"(.’0P5tÅ·ÔAUɲå+Yü0₫ÉÀ\%å-n¾Ê§—ø¦YW endstream endobj 695 0 obj << /Length 218 /Filter /FlateDecode >> stream xÚM1JÄ`…ßb˜ÂÜ`w. ~7»hXW0…àVbµZ * vnâUr”aË!ă›,ˆÍÇđ½™Ç”ëó«K-t­gQË -£>Gy—å²p3%ûWÙÔt¹’pK-¡¾Óϯ ›ûk¶úµx’z«X §˜™ư 33ä…£r¤CF40Œ@:bª ˜#µàLÉ‚¼ªÁ‰Y˜ơ.¹dÄŒ Çæ›¶åAîȺ ălBƒ¼³–{,ªZxËÏ`1K{¯ï+æoürSËN~±¡o' endstream endobj 696 0 obj << /Length 160 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0RĐ5T01P05PH1ä*ä26 ¹†™ä\.'O.ưpcs.} 0—¾§¯BIQi*—¾S€³ï¢m¨`Ëåé¢ÀÀỊ̈ $ơÿÿÿ?Äÿ ` ̉Í#…ø$`'0ƒö üøÄù ́  æÿÿÿÿSÿdÖ.WO®@.’Ø] endstream endobj 697 0 obj << /Length 159 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0RĐ5T01U0¶TH1ä*ä21 (˜@e’s¹œ<¹ôĂLŒ¸ô=€Â\ú¾ %E¥©\úNÎ †\ú. ц ±\. ơÿ`øÿƒùÿ,dưF Éøƒ}üH¤<˜´’ê00ügüÿ¿á?`¨G"íÿ?’üÿ›²̀ÿ¸\=¹¹kqt endstream endobj 698 0 obj << /Length 174 /Filter /FlateDecode >> stream xÚ31Ó³´P0P0bScK…C®B.ßÄ1’s¹œ<¹ôĂLŒ¸ô=€¢\ú¾ %E¥©\úNÎ †\ú. ц ±\. ơÿ́ÿ7üÿßPÿÿ& ‘eüÀÀü€J₫``ÀÀ$ÀÈ? ü@²†¿•´cg@%å4*ÉßPƒF²øF2?ü€F2~~€F2ü?€NÖ7 H{ ærơä äóV endstream endobj 699 0 obj << /Length 195 /Filter /FlateDecode >> stream xÚuν Â@ đˆƒ¥Đ> stream xÚmν Â0àˆCá¡÷¦Ơ(v©à˜AĐÉAœÔÑAѵͣƠ7Q|ÁÅAŒwƯ¤éGr—»œé6³&Ø¢ßt°á&…=>'|äÍz z¦zBQĐvÇĂi z0b z„Ë“Øö½óoUú³÷ YU¨X)Ơ§-ÈØ½ÈFÅFç'{»“ơÇ…¬yVùJtlÉHƒŸ!²r³&µué]Å;7ä­ØR“¹̀CSQñ‹¦ i¬ÊÓÀ́w…HÈÂØÂ>ʳh endstream endobj 701 0 obj << /Length 237 /Filter /FlateDecode >> stream xÚeαNĂ0à‹2Dº%à{p̉.±TD$˜: &ÊÈ‚‰ˆ˜73âẸa+RÅ‘sÔÆ‚ÁßđŸÎ÷—óăÅ)eTĐQ‘S9£“mr|IJ̉ŒæûÑƯ.kÔk* ÔCº¾¤ç§—{ÔË«3ÊQ¯è&§́ëµl [fÛ²cv’ŒÓ¨‡¸ƒh+ẪÄ́¼÷ R PPĂ›Lm5éÄÄ5“wÛƒQ?Ú‹_"|v“¯̃Ö‰&Ô*₫Zư³ ÜIM ê]4̃O©`9k”—å b{0ư‘ưD>€Ø7Æó¯ñùíkƒ endstream endobj 702 0 obj << /Length 171 /Filter /FlateDecode >> stream xÚÎ1 Â@…á aàœÀMˆˆ@ Fp A+ ±RK EÛ‰Gó(Á2EÈ:/u ‹ư—Ùư™Í§éB"Í̀IR9Ç|c»#¼¦ƯÇéÊ…g··™Ưº«ßÈă₫¼°+¶K‰Ù•rˆ%:²/%!Ô•¥éI­Dă¯ẹ±äoKơ²ÊhĐѰ±Œj#0#0£?Y¦` ¦` ¦`]ÚĐ“nS^ỹñÊiô endstream endobj 703 0 obj << /Length 143 /Filter /FlateDecode >> stream xÚ31Ó³´P0P°bSs…C®B.crAɹ\N\úá Æ\ú@Q.}O_…’¢̉T.}§gC.}…hCƒX.Oæö̀Ạ̊@lÅơÿ``âz ₫Ăç¸ÿC?’¾Æöÿÿÿ¨‡à?P æs¹zrŕRZö endstream endobj 704 0 obj << /Length 232 /Filter /FlateDecode >> stream xÚm¿NĂ0‡‘K·xe‹Ÿ'´ 0Y*E"L ˆ‰vdÁÚøÑú(~ªwH‘`¸Oº»ï₫,»óë+ßø•Ạ̈¯.ư¶¥wZt’7jăơÖ=…'¿è(ÜI•Bï??¾vÖ7¾¥°ñÏ­o^¨ßx¸#€È `Î0̀#,óyB=:F̀§˜0¤Àè.O€=¡đ̀ {Å™sØ2tâƯ÷ 9ÈùF¢tJ´£º:ZëTTwHsͪæT«U‹ù!‹ª,†)b˜"†)3₫ÚÈtÛÓ#}çwo endstream endobj 705 0 obj << /Length 239 /Filter /FlateDecode >> stream xÚMбNĂ@ `G"yÉÊv~ö%-aÔ‰ H0u@LбCQ»’¸nÑ館Ñ?I}ûL§¯óưúeCú-½”¿c»%H00cRb†LèƯ5áÁh†¦Ră"̀&\/d À/©„́†„Ná^J¬+J™¯Êx#jCÿ(Ñïä^ ‡NwŒÚ6d`âNùVø?‰1F3:=ª³0+¸(-ª…¶ø aO"{|lñdy‚ endstream endobj 706 0 obj << /Length 196 /Filter /FlateDecode >> stream xÚ•Ï=‚@à%$Ópæ.Äơ¯"AL¤0ÑÊÂX©¥…F;£pJ ¾ÙÄÆØ8“ư’7[¬™syŒc Of|èF&di\%8])ÉHïÙ„¤×˜’Î6ü¸?/¤“í’#̉)"”¥¬”×*¥üîC Ä–(„\èÓ -p- đ¿*XJ …¹Đ pZàZàYjàW °” ¶( ½0 úáG(Yù“bÀ_íÛ/Đ*£½:øp^ endstream endobj 707 0 obj << /Length 217 /Filter /FlateDecode >> stream xڭαÂ@à‘Â4û;/ ›œ„@NÁÂYYˆ•ZZ(ÚÄWÙGÉ#¤Lq́:£Âqå5_1Ằÿ÷ÓîxD1 ¨“Pÿƒ)í> stream xÚ•Í1 Â@Đ‹À49‚sƯ„$«@Œà‚Vb¥–‚•z´%GH™bQgˆq̉80¯˜åÿ ‡ƒqL…Ô÷) (ÑÎÇ#rô(ë—íSjEAŒjÆgTzNçÓe*]LÈG•ÑÚ'oƒ:£+đ¼x*Á´P§dÜ‚éåœHđá.ñ'oÇÓœR(@RB¾Ñü­)Ó`ëêỊ̂Ûn±ÿ´aÿ₫ —§—øöđ\# endstream endobj 714 0 obj << /Length 192 /Filter /FlateDecode >> stream xÚ…1‚PD‡PlĂØ èÄ1‘ÂD+ c¥–m…£q@IAˆû;“WÍÎÎL0›† vÙ xólÎàgnäû¢ºEăét¥4'µgß'µT¾áÇưy!•n—́‘Êøà±{¤> stream xÚ…O; ÂP±lăÜ è{IüÄ* L!he!Vj)¨h-GÉ,-$q̀ƒ´ÂT;ß…ĂñL­NuihuéÉ—›V'Ç/2OǺ4Ĭx“®ơqÅ̀7 ơÅ$º÷Ơ$Mô |€ ¨,G\ WÂ{¡ûFÇ9úé^Ù€"J[|¼ ¬µĐîrè’YÁ"Ö±4nT?…”pGrjƯ¬c_e*[ù«ËM* endstream endobj 716 0 obj << /Length 167 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0U0Q0¶T01SH1ä*ä26(˜%’s¹œ<¹ôĂŒ¹ô=€¢\ú¾ %E¥©\úNÎ †\ú. ц ±\. L@̀Àß$äAD=ˆø$˜ÿÄÿ€Ä?€Ä ‹³ĂÅíáâÿáâ?Å@âP¢&VV̀Œ.ó.ó.S—áG—;́&.WO®@.n=̃ endstream endobj 717 0 obj << /Length 162 /Filter /FlateDecode >> stream xÚ]± Â0†‡Â->‚ÿ˜ÄK…N…ZÁ ‚Nâ¤Îú¨>‚c‡bMN8¤>È÷] çy’°ÈáÁü GGbÎÂO%ÎT2[0“YFK&¬p»̃OdªơLƒƯS¨AZZFư¢HW 2"ẶL}¦¾Tß©o₫ưï»­® ËĐ"І¾Öº?¦ endstream endobj 718 0 obj << /Length 114 /Filter /FlateDecode >> stream xÚ31Ö3µT0P04WĐ5W01T0µPH1ä*ä22(˜™B¥’s¹œ<¹ôĂŒŒ¹ô=€â\ú¾ %E¥©\úNÎ †\ú. ц ±\. ơÿÿüÿÿ†₫üa`üè?’›îçrơä ä—5ez endstream endobj 719 0 obj << /Length 116 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0VĐ5W02W0µPH1ä*ä22 (˜™Bd’s¹œ<¹ôĂŒŒ¹ô=€Â\ú¾ %E¥©\úNÎ †\ú. ц ±\. ơÿÿüÿÿ‚êÿÿc`¨ü¨æ`°›ÿp¹zrrléI endstream endobj 720 0 obj << /Length 175 /Filter /FlateDecode >> stream xÚµ± Â0DQXúKä'2̉† á * D” ¨Ăh%#¤¤Âü#6HáWÜỴóMíÄÈà0Ăp œsº‘µf˜¹Øœ®Tz2{XKfÍ1¿Áă₫¼)·Käd*rdG̣”R/¥RA-œ%¡a|¸½Ư Đ‚´V$‘Q¬ùµñễoÄ×e«ú¿U¿ïG+O;ú‚a endstream endobj 721 0 obj << /Length 171 /Filter /FlateDecode >> stream xÚµ± Â0EQ Ưù €miCp¢ ” ¨“Ñ…(©0¾ó i~ñϧ{~37ơ <& ¸ ~‰³¥9—Jƒ¹Ï“öJu }€s¤7©&¶xÜŸ̉ơnKºÁÑœ(4è^J©øåøqÄ^©.JùNQrŒ?)F#ŒPäëQ1H¢)3RŸ;™Ê;Ù˜J~.؆xCÙˆ?ZÚÓOYbÍ endstream endobj 722 0 obj << /Length 104 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0UеP0¶TĐ5RH1ä*ä26 (˜A$’s¹œ<¹ôĂŒ¹ô=̀¸ô=}JJS¹ôœ ¹ô]¢  b¹<]êÿÿÿÏÄÿа—«'W *› endstream endobj 723 0 obj << /Length 171 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0S0W0¶P01VH1ä*ä26(›%’s¹œ<¹ôĂŒ ¹ô=€¢\ú¾ %E¥©\úNÎ @Q…h –X.OæöX±û́́₫±ø÷Ÿưà¿ÿÇÿûÿüü?ûÿÿđÿÿÿ€ùÿÿÆÿÿêÿ€1ˆ ÉÔ€Ô‚ơơ‚̀™2—} ·p¹zrr«xSº endstream endobj 724 0 obj << /Length 116 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0V0S01T01QH1ä*ä26E-Àɹ\N\úá Ææ\ú@Q.}O_…’¢̉T.}§gC.}…hCƒX.O† øA-Â₫ÿÿÿ€øÿ4‚v@  Ă¹\=¹¹emH™ endstream endobj 725 0 obj << /Length 136 /Filter /FlateDecode >> stream xÚ31Ö3µT0P04UĐ54R0² R ¹ ¹ M€Â FÆ0¹ä\.'O.ưpC.} —¾§¯BIQi*—¾S€³‚!—¾‹B´¡‚A,—§‹ƒüûơ?€đÚÿ‘ÿĂÿ‡áÆŒ?˜?°PàĂ P—«'W Ÿ̉,5 endstream endobj 726 0 obj << /Length 99 /Filter /FlateDecode >> stream xÚ31Ö3µT0P04F †† )†\…\@Ú$l‘IÎåṛä̉ pé{€IO_…’¢̉T.}§g ßE!¨'–ËÓEAÁ¾¡₫Àÿ0XÀ¾AËƠ“+ ‰;“ endstream endobj 727 0 obj << /Length 157 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0UĐ5W0¶T0µPH1ä*ä26 (˜™Bd’s¹œ<¹ôĂŒ¹ô=€Â\ú¾ %E¥©\úNÎ †\ú. ц ±\. ́@̀Àß#äÁH̀D؈:Q'₫€ˆ@̀&> f0ñd˜82î>3Ñ dfâ ¸™¢Dp¹zrr@Ä:Ơ endstream endobj 728 0 obj << /Length 107 /Filter /FlateDecode >> stream xÚ31Ö3µT0P04F Æf )†\…\††@¾ˆ –IÎåṛä̉W04ä̉÷ sé{ú*”•¦ré;8+E]¢zb¹<]ä́êüƒớäđ́:¸\=¹¹{-= endstream endobj 729 0 obj << /Length 155 /Filter /FlateDecode >> stream xÚ31Ö3µT0P04UĐ54R06P06SH1ä*ä24 (˜XÀä’s¹œ<¹ôĂ M¸ô=€\ú¾ %E¥©\úNÎ †\ú. ц ±\. ü ̣́Ô€Aụ̂øđ öêá´ÿ#ÿ‡ÿÆ ?0`ÿ ÿ ₫Àÿ†ÿ@¡.WO®@.…8 endstream endobj 730 0 obj << /Length 110 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0V04S01T06QH1ä*ä26 (Z@d’s¹œ<¹ôĂŒÍ¹ô=€Â\ú¾ %E¥©\úNÎ †\ú. ц ±\. ơÿÿÿÿÄÿ °‘§\®\\ºâA endstream endobj 731 0 obj << /Length 103 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0W04S06W02TH1ä*ä2 (˜B$’s¹œ<¹ôĂŒ,¹ô=L¹ô=}JJS¹ôœ ¹ô]¢  b¹<]êÿÿÿđÿÿÿ0 âs¹zrrå$~ endstream endobj 732 0 obj << /Length 117 /Filter /FlateDecode >> stream xÚ31Ö3µT0P°T02W06U05RH1ä*ä22 ()°Lr.—“'—~8P€KßLzú*”•¦ré;8+ré»(D*Äryº(Ø0È1Ôá†úl¸;¬c°Çí Èl ärơä äÇ\+ß endstream endobj 733 0 obj << /Length 168 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0bCSC…C®B.cs ßÄI$çr9yré‡+›sé{E¹ô=}JJS¹ôœ€|…hCƒX.Ov₫;¢ù†: ÁPƒNØÿÿÿÿÿÿF0Ø1ü`€uŒ@¢†ñQÄf ñƒù„Àf2ØJǼó~ ñ€¿‚ñ;—«'W ÇsË endstream endobj 734 0 obj << /Length 239 /Filter /FlateDecode >> stream xÚ1NÄ0Dg•"̉o|û$Q6ÍZZ‰HPQ *–’‚Ở!́£ưp!eÙ8âi¾ư=o¶ưƠpíZ·-§uCç|H?Đ¯¶\¼¾Ë~”æÉơƒ4wœJ3̃»óéóMưĂ£?¸çε/2"På˜<>Ïå uÁfA@5Ă£`c̀O4ês´1dµ1gơÊ®ƒîêɧï:ÙôeÔPø~•KÙœ-ª˺QvơOÔhù9–ŒX̉ÀÜ…H$%Ë RM Ÿ̉ZÉlémb– „d·Ùr)}ÙA!·£<Ê/}L~ü endstream endobj 735 0 obj << /Length 184 /Filter /FlateDecode >> stream xÚmÉ=‚` à’.À߉1‘ÁD'ă¤]…Ä‹‘8p n #¡~ $(}úö­ëL<ŸL²å¸6y6í-<¡Óvf{¶ƯĂÅÅ\¶(â]Î×p9% ED‹̀-Æ4 đ•Ógö&ëÉ{ô¼øâ!1îå¥qƒú?µ\ÀÜ P˜ùCÁµ#ưA“dZz–4Àu ×,iºÔu8‹q…/ÂaoM endstream endobj 736 0 obj << /Length 190 /Filter /FlateDecode >> stream xÚ}±‚0†K:˜ÜÂ#pO`iÀ‰1±ƒ‰NÆI4º æ£đơ®ØîKÿëƯùÓd¹Ê0FM•j\i¼jx@½˜%\îPPGL2P[ê‚2;|=ß7PÅ~¤K<ÑäL‰•s ´Â9×óËy|¥9#l K#‚vÓœ_ó[¹Z²½äC„N ̉_‹¦C£•èFôŒÏ,úa8è—‘[NÔøXT®®₫Q­€ü÷âƯ endstream endobj 737 0 obj << /Length 218 /Filter /FlateDecode >> stream xÚÏ1NĂ@Đ¹°4¹¬—QY AÂTˆ (‘A‹ĂÍrÁå 3AzẀJÿ_¤ăæ”kN|y¹9á‡H/”–v¬¹Iû—û'Zun8-)\Ø™BwÉo¯ïVWg)¬ù6r}GƯÅ3J•~ ZưôªưT™Mè¥Øa.åˆÊ)¥œ- ™oö̀¤Å/½ó`t™œƯÿ˜₫Rôø27ÈäVÖ¯½ifđöƒíh·¾hăÛ`+-·Rû¡ÔÑ̉́Nç]Ódvg9 endstream endobj 738 0 obj << /Length 183 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0bCSC…C®B.c ßÄI$çr9yré‡+[pé{E¹ô=}JJS¹ôœ€|…hCƒX.O…úÿÿ₫ÿÿD|?€bØ0ÿ ÿAD}°̣€ÿÁ&> f0ñH0b!₫O ¶ƒn%Ørv¸ƒÀî³?sóˆ?À>û æË `Ÿs¹zrríÇG endstream endobj 739 0 obj << /Length 147 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0b#SC…C®B.c˜ˆ ’HÎåṛä̉W0¶ä̉÷ré{ú*”•¦ré;8+ù. ц ±\. ơÿÿÿÿÄÿ Øæ Œ„ † ‚ƒ`|$€lthv›bˆ)ØŒ‡6 ¢ä£ÿQ Ø.WO®@.̀Œ‡r endstream endobj 740 0 obj << /Length 145 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0bCSC…C®B.c ßÄI$çr9yré‡+[pé{E¹ô=}JJS¹ôœ€|…hCƒX.O…úÿÿÿÿâÿH́ó"ˆ Á€ƒø$`@±ØCLÁmQDưÿ ÿ!Ä( ,ÆåêÉÈæxô endstream endobj 741 0 obj << /Length 227 /Filter /FlateDecode >> stream xÚĐ=NĂ@à±\¬4๬¥PY AÂT(PR$‚Ö̃kÍ ¸7eU†ÙI"Q̉|Ǻß{;—Ư5袥ùŒº½´¸Á°ĐaC]8®<¿ár@ÿHa₫VÇè‡;zß~¼¢_̃_S‹~EO-5kVE*#ṬÉPËaa¥'\¦BÙƒ°û‰«oè¹̉\Qéơ4÷pf<á¢`2éß”²Oà$‡̀˜găßëíµúD> stream xÚ31Ö3µT0P0b#SC…C®B.c˜ˆ ’HÎåṛä̉W0¶ä̉÷ré{ú*”•¦ré;8+ù. ц ±\. ơÿ₫ÿùÿŸñÿ?cÀÀ€êÄÿÿÿ±4± Nàô%—«'W ˆ‡ä endstream endobj 743 0 obj << /Length 108 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0bc SC…C®B.crAɹ\N\úá Æ\ú@Q.}O_…’¢̉T.}§g ßE!ÚPÁ –ËÓE¡₫ÿÿÿÿÿÿĂ >ÿ†Á±¹›ËƠ“+ H¨X~ endstream endobj 744 0 obj << /Length 123 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0bCSC…C®B.cs ßÄI$çr9yré‡+›sé{E¹ô=}JJS¹ôœ€|…hCƒX.O…úÿ₫ÿÿ€L€Å˜ŒÁN|Œ?ˆ êÿÿÿÿă?*ûÀåêÉÈé f’ endstream endobj 745 0 obj << /Length 177 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0b#SC…C®B.c˜ˆ ’HÎåṛä̉W0¶ä̉÷ré{ú*”•¦ré;8+ù. ц ±\. ơøÿüÿÀ ÿBü`°ÿW$₫đ‰ü{ª1ˆy Ÿ‘‰ùŒ0¢Ÿñ1Œh†í͇ÄqÑ|¼F¼‡ï™aÄ Ñ𕨠‚l¢è·?`¿!°—«'W ±,ˆ endstream endobj 746 0 obj << /Length 194 /Filter /FlateDecode >> stream xÚUÏ-Â@à%ˆ&c¸̀ 迨¤”„ P‚$¤u½Ö’[GEÓev›¶ æK̃1Çî»hÑ8º&nL؃-;CF¹XïÀA_ í>¡ôpÇĂi º?!å—&+ŒRå"c¢(ɉ(§N+˜ÆµGÍSroˆ‰›‚W\¯‹"­à¬æüÏ ¦+éƠtI…–đߣmÅ›h5|Ö ¸üˆ‹¢dXB]/†qsøº‰| endstream endobj 747 0 obj << /Length 170 /Filter /FlateDecode >> stream xÚÅ1 Â@ERÓx„̀t³)R-Än!he!VÆ̉BÑÖä¨9‚¥EØq™†Wüßü7sæe”ÓÄ”Ϩ¶xAæƘ‡æxÆ̉£Ù3UŒÑø5Ư®÷r³ ‹¦¢½¥́€¾"h é`,̣‚T¤'ÀuID ˆ§x¸/„ˆ¶Hÿ ¡øÙ÷®î9 ƒ›Zª¯ëpéq‹o¡lª endstream endobj 748 0 obj << /Length 174 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0bSC…C®B.cs ̀I$çr9yré‡+›sé{E¹ô=}JJS¹ôœ€|…hCƒX.O…úÿÿ0üÿÿÿˆø"₫3Å₫70`øH؃₫@‚ưŒ`?€#^¬„ù^°Q`Cƃ-YÉ ²œä fƒ€² Ô$êÿ700€ F"Àb\®\\æ„wN endstream endobj 749 0 obj << /Length 197 /Filter /FlateDecode >> stream xÚ•Đ¡Â0à›jrfĐ{Ø::"#a‚‚ ‰€€î̃ e0‰XvtmC‚ùÄßöîOơh˜)¦„´¦TÑ^á µ²aLiâOvG̀ ŒÖ¤FscT,èr¾0Ê–S²iNûf‹EN†`æ̉Y9†»Q‰¶3p‚qNÊNÙ3¼ÿ¶ßO0ïÉn‹ßè¶ ×ÄZ¿’J4½&}₫5tỆ›¦y+™A²ư ½-ؼ+Ô€³Wø2>z endstream endobj 750 0 obj << /Length 236 /Filter /FlateDecode >> stream xÚu1NÄ@ E½Ú"’›a|˜„$ƠHË"‘ * D”H»$*â£å\!GØ2HQ̀w€‰æÉăÿmÿ©«ăæT ©å¨”ºæDJ̃sƠ ‰gơ­Ü?ñ¦åx#UĂñmí¥¼<¿>rÜ\IÉq+·¥wÜn…˜™åº2ûĐ̀̀4w„C0Mư€¤LúNÔéL”túAø ¨9Áç̉„Éa=tC¹6”8y€ÇF¢̀›Ôa¥OÚ2éư/̣aÁ<Ăô&ÄØùE>où¿åxv endstream endobj 751 0 obj << /Length 124 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0b#SC…C®B.c˜ˆ ’HÎåṛä̉W0¶ä̉÷ré{ú*”•¦ré;8+ù. ц ±\. ơÿÿÿÿÄÿÿ¡êêđ@†H0 zÂ₫ÿ(Qÿÿ—ËƠ“+ +̣T¬ endstream endobj 752 0 obj << /Length 167 /Filter /FlateDecode >> stream xÚƠË1‚@…áG(L¦á̀tYY +ÄD ­,Œ•ZZh´†£q@IaGhôf'_ñϬ‹gÉ‚#}SËÎqbùléF.b27§+e™=»˜̀Z3™bĂûóB&Û.Ù’Éù`9:R‘s)U*µH]JóíØư^‡¿w˜ŸøÂ¤Ôè¨%ÂH«´RQCôª/ê‰~ú´*hGo8‚˜ endstream endobj 753 0 obj << /Length 189 /Filter /FlateDecode >> stream xÚè;‚@€á!$Ópæº,‚1q ­,Œ•ZZh´.FÇ5¸”\5o’2ă¹s? ›q̣̣98^Ñ}G›|ç»9^0ÈväÈV2#kºßgdÑfAYL{NöELi iÛwĐw?>Í,À῭ ̀ʰ ]’ xB˜i ¿´LHäÊ›1ṼL0óJR₫a”…¢Vèu¦èZ À¥À-¾̣Vi endstream endobj 754 0 obj << /Length 197 /Filter /FlateDecode >> stream xÚϯ ÂPđ#†Á)>‚çt»ºËÂœà‚ É &5mÂ.øb_CY°N wíztøo,È¿đNǿvÓéE‚‚́69‚æWh .-rZùe¶D/@sL¶@³Ï5Á€6ëíMoØ%n}đÏŸÂ :ƒ–ßæ}v%Ö$@ö—F•´T÷iX°z̉ûÓ[ơñ¬¿VÎÉ!zyḾ-¹ß+_ªX=”Ey>JÍ3CN™.°àï{ŒK endstream endobj 755 0 obj << /Length 182 /Filter /FlateDecode >> stream xڥϱ Â@ €á”Y|„æ ¼–¶ƒ j;:9ˆ“::(º¶}´{”{„̉3‘̃̉Ơ!äH–ÎóÅ”ÉÄ”'tIđiÎûo•ó Ëởơ†_Q×[z>^WÔånE¼WtL(>a]Qáœ3-c'4‘aÎÓÓ|` ÁBAơ™I=E’zNG₫KCö ¬8e  œpª¬“‹&È•×5îñ ûÚlÎ endstream endobj 756 0 obj << /Length 191 /Filter /FlateDecode >> stream xÚm̀= Â@à Óx„¸ ‰‚Ơ‚?` A+ ±RK E[“›™£ä)S,;Îh%X́ûfæùh<¥” }å:exÅ\³T¿:8^pV¢ƯQ>E»’m¹¦ûíqF;Û̀)C» }FéËEÜ$ s­´àXBט^H”ȃ©ÁĂ@?|be¨®ŸàzY©E—ƒâÿđTZ_Ơq×-`öRÅ!a~…ˆƒ„®K<.KÜâj/\ endstream endobj 757 0 obj << /Length 187 /Filter /FlateDecode >> stream xÚ= Â@…g°¦ñ™˜„Ä"•#¸… •…X©¥…¢­ÉÑr”aË€!ăN;±˜æï½GÓY‡®âg!ŸBºR¤³@[]/”̣w%ä¯Ü”|³æûíq&?Ư,ØơïƯåLƹ©¿+đx•ƒ“À—´€"̉¡@±y‰Rx Œ-¶0ª±é₫~Đ*?¢uîmÖ½rç!0±ƒe¥æ] ÔEÓ`ç%Đ̉Đ–̃*Åsz endstream endobj 758 0 obj << /Length 182 /Filter /FlateDecode >> stream xÚ1 Â@E¿¤¦Ik—9›°° Än!he!Vji¡h›äh%G°L2ΦĐÖ…}đgÙ?of§óÇœêÅlS>'t#k5Ñ?œ®”;2{¶–̀Z§d܆÷ç…L¾]rB¦àCÂñ‘\Á¤"iJzŒDˆÆ=á[5/”ÈjLAOåQ~Ñư‰ß¡@«B_ƠZ¯h4èÊJ—â5¡Î«µ^RMuZ9ÚѲuEJ endstream endobj 759 0 obj << /Length 193 /Filter /FlateDecode >> stream xڕα‚@ à’.<} L— &̃`¢“ƒqRG®â›á£øŒ—;[pqÓᾤ½´ư 5)+ÊHñ+•9ís<¡’^&¥|́XLפ*LçÜÅÔ,èr¾0­—S⺡MNÙMC±€Ä  ÿ$z1Ú1̃wxï!"Ëûâ>ô<æôZ™iá&³N°?â>cíH ăRa¸ÊÉH'c Ë:ÇÑ´m™¸O,Î ®đ —ºYK endstream endobj 760 0 obj << /Length 201 /Filter /FlateDecode >> stream xÚm±ÂPEï’âÁ4ù„̀́Kˆ¬® ›BĐÊB¬Ôr‹mM>í}ÊûËấ}V̀™;ܹ“ú³™i©“Ô¥ÖS=Ṭ'uĂù9&aÿ+óNüFëFü·â»¥O—£øùêK+ñ ƯVZî¤[(²€ÂĐÛ f#2³;܃J>ÂPD´Cˆv@Z }•ˆ„‹÷c½C  ¤7¸¾Đ'Đ* 4u‘ö.æ7ú¹mp ̀b2ræcẠ̀ƯÉZ₫I÷_₫ endstream endobj 761 0 obj << /Length 154 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0asSC…C®B.cßÄ1’s¹œ<¹ôĂŒ¹ô=€¢\ú¾ %E¥©\úNÎ @¾‹B´¡‚A,—§‹ÿû@âÿÆÿÿ˜AûŸz ñHđ?°*;&pơÿÿÿ4A€Åđk£aÿÿÿ[~ `1.WO®@.̣Å^£ endstream endobj 762 0 obj << /Length 253 /Filter /FlateDecode >> stream xÚ}±JÄ@†ÿ#E`}!óÄä”k.p` A+ ±RK E»#›ÎÇđỤ(y„”[,g‚²́ǰóÿÿ̀ÖƠÉzĂỴ̈q¹áºâꜟJz¥º`;볟Öă íZÊï¸.(¿̉wÊÛk~ûx¦|wsÁ%å{¾/¹x vÏ’€4¸ˆlnfxYé•DdöItÁ§S¶n\Å#7@efd=º`’El6X4jB*²`„éá¾fÀ}E_éh0‡íb•ôj“1SLÍ€,xƯ>v*‹Å!*:MĂö–Æ¢ó½:²?-y‰%Û§F‚Í@—-Ử7ăè‚> endstream endobj 763 0 obj << /Length 161 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0bcSC…C®B.ßÄ1’s¹œ<¹ôĂL ¹ô=€¢\ú¾ %E¥©\úNÎ @¾‹B4Pe,—§‹Bư øÿ¬“Œ‘̣@dư ùóÿ? ùûÿ ùB~°o’äAdƒü ÉÀ$ÿÉ?Häz“ơÿøÿÿÇÿÿIˆ8—«'W ƒzú endstream endobj 764 0 obj << /Length 132 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0bcKS#…C®B.cC ßÄI$çr9yré‡+ré{E¹ô=}JJS¹ôœ€¢. Ñ@-±\. ́ ̣ Ø₫ĂÄ@̣x@ưÿ@ü€á?×C1;}pưÿÿ₫ÿÿÿ†A|.WO®@.üØO) endstream endobj 765 0 obj << /Length 169 /Filter /FlateDecode >> stream xÚÍ= Â@…_°¦Đ#d. ›ÍŸ B Fp !Vb¥–¶n–£xK q\‘`eïÀW¼ïñ‰£~2â€cîé!G“·¦ÎO¤j‰Ô .»m÷Oñë1üêâ₫dXˆ÷„ÈVî|¹¢-M -è§úX endstream endobj 766 0 obj << /Length 198 /Filter /FlateDecode >> stream xÚ̀;‚@à%$Ópç̣.¨H)L´²0Vji¡ÑV¸‰Wá(xŒ…[Æ_­Å~Éü³ó‡Á0ÑEŸ_ècäáÆƒ=’¹2Êb½ƒ4gA ΄Sp̣)§-8él„ôŒs˜ĂQ¹yÀ endstream endobj 767 0 obj << /Length 115 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0b e¨bÈUÈel䃹 ‰ä\.'O.ưpc.} (—¾§¯BIQi*—¾S€³ï¢m¨`Ëåé¢PÿÿĂÿÿ‰zÁÀ<Œˆúÿÿÿ7ñÿ,ÆåêÉÈî{\W endstream endobj 768 0 obj << /Length 171 /Filter /FlateDecode >> stream xÚ½= Â@…·[˜&GÈ\@7!Q°1#¸… •…X©¥…¢ơ^,7đæ[n±́8Îȃ÷WĂÑ3ä‚r„Å9œAl&’ø]ö'¨-˜\À,¤c—x½Ü`êƠ s0 nå¹Û =œî=Cê¿bq䙣̉1 S¥e¬”ö‰K•vI'́’ö‡mrÿ/)Ṭ́8R`ßû¾‡¹…5¼ízfÊ endstream endobj 769 0 obj << /Length 155 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0bcc3…C®B.ßÄ1’s¹œ<¹ôĂL ¹ô=€¢\ú¾ %E¥©\úNÎ @Q…h ÊX.O…ụ́₫ÿ¨ÿ$₫ÿ$ÿÿÏÀPÿD2₫ÿ`ß$ȃÈù@’H₫“Èô&ëÿ?:ñÿÿÿÿ7 “q.WO®@.‹£ll endstream endobj 770 0 obj << /Length 183 /Filter /FlateDecode >> stream xÚ}=‚@…‡XLĂvNàBL¬H·0ÑÊÂX©¥…F[Ù£íQ8¥…a†‚Îb^2ï}¹™KJ)*%³ K†w4÷̉‹ó +‹ú@¦@½á)j»¥çăuE]íV”¡®é˜QzB[Ä_P¥ ¢:˜…đá9o’.êAµ@9(¡dq%Ÿ»7@â'a¸ư/=ßµÓGĂ.^¬ÄTyhÆ ‰”pÁ A!\\[Üă>P: endstream endobj 771 0 obj << /Length 200 /Filter /FlateDecode >> stream xÚ¥= Â@…g°¦ñ™ èfI"¦üSZYˆ•ZZ(ÚÍ£ä[.(w“€–‚S|Åæ½7q4HRYs_8Ö ù éL‘WCNâvµ?Ñ$#µá(%µp:©lÉ×ËíHj²²&5ă­æpGÙŒs” V,ÈS*7;(& A‰]ƒt,¾à -À•ÇưGTÎÀµ@Û8×=ÓF–>¼®á ¡¯†¾$Úñ¼Ë_È¥÷ªùF­Ñ<£5½̃¯́ endstream endobj 772 0 obj << /Length 211 /Filter /FlateDecode >> stream xÚ­Ï= Â@à‘ ÓäÎ4 ÙˆVÀ‚Vb¥–¶&7đJ{¯à Lig³ Z 6_ñB̃¼Ơq;éQH1µ¢.é„â­#Ü¡$ )ѯO«-ö3 æ¤# Æ’cMè°?n0èO$ẹ́Ó³!W© É¾Èùb Á|3à1³ơP¢_6Äæ¬ri©Ölxz+=Ơ>jO=®Ù]qƯu¿ốªÊç÷B·V–ŸÅ´~…º[ëÎÿ)×DÅ\|kse8Ă'á·vG endstream endobj 773 0 obj << /Length 158 /Filter /FlateDecode >> stream xÚ­É1 Â@ĐŸJø—đŸÀƯu£Äj!Fp A+ ±RKAEëơh9J¼AÊÁqc!Ú[̀ƒ™Ií`4-Ă˜ÔˆË̃đ™m»îjẃœ{Vk±«y\Yù…\/·«|9Ăª½e_Hx’+5ĐCôÑ8´äÂ#‚$̉RC®¡¹ˆ\ơ¡́¸ÿBÿ"¨¿xo<ó¼âơơIw endstream endobj 774 0 obj << /Length 185 /Filter /FlateDecode >> stream xÚMË1 Â@Đ‹À4!s7q5Æ@T0… •…X©¥EÁÊÍÑrr‹ñ,,̃2³óÿÔg©D’€MÅ&rùÆv‚=ê×₫pºr^°Ù‹°Yă—M±‘Çưya“o³YÊ!–èÈÅRÈùr¨êGB®ù7 }Kïÿ´D#"×eZS¨¡W¡ÿ!§ˆ("P÷B Ca÷£}­¢9ª6A«ª=> stream xÚ31Ö3µT0P0bc 3…C®B.cS ßÄI$çr9yré‡+›ré{E¹ô=}JJS¹ôœ ¹ô]¢  b¹<]ä€À¢₫ÿÿÿ @ü¿A€ÅH2…‚ù`€hàÀ ß €A₫Aư~ [@óÿ Œÿ€LxÀÀåêÉÈ₫:B„ endstream endobj 776 0 obj << /Length 148 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0bcc3…C®B.ßÄ1’s¹œ<¹ôĂL ¹ô=€¢\ú¾ %E¥©\úNÎ @Q…h ÊX.O…ú̀ÿ₫ÿ`ÿ…¬ÿÁ $0đ()DÚÉ? ơ₫ÜÆđêdƒ=˜”ÿH2ÿcÿÏÀåêÉÈÄ£d> endstream endobj 777 0 obj << /Length 186 /Filter /FlateDecode >> stream xÚ5Í= Â0ÀñW:oéúN`ú¥ĐÅB­`A'qRGE7©…^̀­×è êØ¡4¾Ø”É? ‰Âé,&Q@áœÎ>̃0ÔÍÓ[}pºb*Q́)ŒQ¬¹¢zÜŸévI>Œ>yG”½•¥:ÅôJ•^ư›]ƒS |Á-,ZHZX:È^<rœ[CÂ×Á准’qÊz¤b&Ơg¤á¦QŒ¥À½†¿À•Ä₫$›Lă endstream endobj 778 0 obj << /Length 174 /Filter /FlateDecode >> stream xÚ31Ö3µT0P0bcc3…C®B.ßÄ1’s¹œ<¹ôĂL ¹ô=€¢\ú¾ %E¥©\úNÎ @Q…h ÊX.O…úÿ `Ôđÿ?ĂÙaCÄÙ00~ @2?ÀDv`²N2~¨+₫ß ¿#Èß``’ ?Ÿ‡“¿¿G#«¾g``¨?øA6 Hû†@R¡†ËƠ“+ Ém¢ endstream endobj 779 0 obj << /Length 202 /Filter /FlateDecode >> stream xÚEŒ; ÂPEoH!Lăœø£‚UÀ˜BĐÊB¬ỔBÑN!…Û²³t î@Ë!ăL@,̃aæ̀»·µ{¸£¯Ûá¨ÏÛ™ lµĂfOÄܒ£¹©ZrÉŒOÇóÜp>âܘW!kJÆ‹/ŸLnRüQ;”H¡(Ô+€Øû­Üp{Íçh¼¯€/ O ¨.†êçê«oŸk> ¹¶´¬4¶ú…¥4Wè¬&F&”™äR¢ª§ÚÑ$¡}¨xY& endstream endobj 780 0 obj << /Length 237 /Filter /FlateDecode >> stream xÚEαjĂ@ àßdˆ‚Ázö́Ø)ÍCB=̉©CÉ”d̀Đ̉nÆvÈĐ×jé‹:tÍ&É=ûîî$%ñÍpÄ!ø:ºădÀñ-¯"z¥X£!—Znh’‘yæxDæQâd²¿¿}¬ÉLæ÷‘™̣KÄႲ)—Ö³µ[{²v§È­ơöđ+ïđOPy5À‘ Æ@®²ä̀©¤äUíđ·-Gÿ[ùÙ;z¿Êßàµ[*ö‚l”ăBÉ;¥v\ɼHer”;åSú¾H‹R §Z88 ¾~íKôÑßÍa{ endstream endobj 781 0 obj << /Length 176 /Filter /FlateDecode >> stream xÚ}1 ÂP †S2Y<‚9¯Å*B¡Vđ ‚N⤮­Gó(ï¤Ï¤c‡|?!?É'ăéœSèä3>gt#Í”»Ơ§+•Ü^wrë~ĂûóB®Ü.9#Wñ!ăôH¾â"Æ…ôPŒ‚¢x+—"B I À/ >¡€i`˜¦$fà_£…$h¡¨†¢j(ª¡D{£{-ĐÊÓ~æêb° endstream endobj 782 0 obj << /Length 203 /Filter /FlateDecode >> stream xÚ= Â@…_°L“#8ĐMLRØđL!he!Vji¡h'£å({„”!qœ-–6ß²ó`ö}›ÄĂt̀!'<ˆ8 9ñ1¢ Å© å»äp¦iNfËqJf)c2ùo×û‰̀t=ăˆ̀œw‡{ÊçŒ̃@Đ²¶^m ´­…ו„û•WĂ·¨”x:ô däTLdOñ”€_Öû'¤X`–*ºw]!W̉¢qµ½z¨‘º9KơUóïĐ"§ }}dĂ endstream endobj 783 0 obj << /Length 141 /Filter /FlateDecode >> stream xÚ31Ö3µT0Pac S#…C®B.# ßÄI$çr9yré‡+Ypé{E¹ô=}JJS¹ôœ ¹ô]¢  b¹<]Øø Xí¸ˆÿ7001;×ñ¾Äójä‘Ô®ÿÿÿÁÿÿÿ?À0ˆÏåêÉÈÅFJÜ endstream endobj 784 0 obj << /Length 222 /Filter /FlateDecode >> stream xÚe1N1Eÿ*…¥i|„̀ đ.›-V Ab $¨(U ¤A›Ư£ù(>BÊÑóÓ„,?kÆÿWíEw¥µ®¸kí.ơµ‘i;¯O%/¶ï²$=iÛIºó®¤á^¿>¿ß$­n´‘´ÑçFë6x0ڄʬ ˜íÍX⌾T†~ÂèËϰœfGvÄlâgØ×ÎOÈ —˜À<|đHTGÇ‚+î©¥µ§Ë‡D5ÿWôTŒL3ü*Ù¡¸=·‡2ÿĐ₫‚½,·ƒ<Ê8hñ endstream endobj 785 0 obj << /Length 226 /Filter /FlateDecode >> stream xÚEĐ½NÄ0 đÿé†J^̣ñ @ZÚHH•îC¢L ˆ @°̉>ZåáÆ§úl·ÀŸDZăTåe}Í9W|Qp•s}ů}PYkP·å|̣̣N›–̉#—5¥[ Sjïøëóû̉æ~Ë¥?œ?S»c„€Nz¬DÈDF‘â˜Mˆ&4=:4§WâĹ• «hLºVÆÚÄQ—5Aưâ1;Í,̣w×Ki üs°Ä™ăÇ…à Îdw;«̉-¯—y"ŸÍ§\Û¼>¹ÿí[z 3áVc4 endstream endobj 786 0 obj << /Length 181 /Filter /FlateDecode >> stream xÚ•Ï=‚@à!$Ópæ.¿ bâ&ZY+µ´Đh £pJëL±hë$ó%ó^5Yº̀ (áÍʺÄxÇT²HN)Î7¬4ª¥ª §¨ô–×Uµ[QŒª¦cLÑ uM₫ÁÄ„B9Ó̀Æ›‹‘ñGĐ3aç(if ăMÅ( Œ/½#́˜`Ëc„÷—V2öOZË¿Z;ư®5îñÜ₫tư endstream endobj 787 0 obj << /Length 207 /Filter /FlateDecode >> stream xÚ¥Î= Â@à‹À4{„̀t³&)!à˜BĐÊB¬ỔBÑÖ,x¯’£xË’qFEĐÖæƒÙ}o“¸v)¢„Z’ˆRGk‡;ŒSʱóÚ¬¶ØÏÑÎ)NÑeŒ6ŸĐaÜ íOäĐiá(Zb>$Ă\CÈ̀ßÈ̀üǹ.́5ïªTʺ)ñ7¢ ½œùPĐ €ù\è)'…ߘ'å-,e›ù$9ó̉‘• i«̀Œ₫ `¾AƒỶ Ö G9Îđ-²c— endstream endobj 788 0 obj << /Length 241 /Filter /FlateDecode >> stream xÚm1NÄ0E”"̉4¹ @’T––E"Th+ ¤Ø´±æ£ø)S„ ăÍ“ü=3ÿuíEÅ5w|̃pWsÉ/ ©í5ÔgûưóüF»ªGn{ªn5¦j¸ă÷ÓÇ+U»ûkn¨ÚóSĂơ†=6™̀@! `dƠHpÑë³Îç³¢˜¢¢Œ°0g0º°¿p ă†\ÏF<'Ÿ"D´MÖbLz[‚Îë€ơZj6]*7DEñă?°?(£j”A…LP5ăË GƠÔ¡˜µ(O•Y*G̉@BRƒæ ›è ₫5pI endstream endobj 789 0 obj << /Length 183 /Filter /FlateDecode >> stream xڕͽ Â0à+Â-¾̃ hÓ NB­`A'qRGEÁÉöÑú(}„¤zW©Eqñ _Èå~3°#̣) ¾¦À';¤Æ#ËI~×Ïö€¡Cµ"cQÍ8ÊÍé|º́Q…‹ iT­5ùt]ăÁ‘ Ù'é`œ010%p1ßà ­‚içBÆt*R¦—€t 2;nB)¼û½¢¦•×4ăª™_T+~Ѭư‹.œ:\âăM† endstream endobj 790 0 obj << /Length 213 /Filter /FlateDecode >> stream xÚ}O» Â@œ`q°M>!ûz‰I «€0… •…X©¥…¢­É§åSü„”Áơ²W؈p w»3s3Y:Ê'sÆĂ„³˜ó1ºP»¡{¦~s8Ó´$»å4'»tc²åo×û‰́t=ă„́œw Ç{*ç Ó(¤Dˆ¼`D:„y#jAÔ BQ»SQ]9h@ø”¢9…׆mđÆ 3/"-PIÿoÓ™n•§ ƠªË×ÙñÍó?|ÉR3{¿¾‡6̉nÚRûúæ}Z”´¡ëån endstream endobj 791 0 obj << /Length 245 /Filter /FlateDecode >> stream xÚm1NÄ@ EmÉÍa|HB’b«‘–E"Tˆj¡¤`í&G›køéHÅü 4̉ÓØ£ñnêóv+¥4rVISJ{!O¿rƯ¢‰²₫~9¼đ®ăâ^ê–‹k´¹ènäíø₫̀ÅîöR*.ọ̈PIùÈƯ^(Ÿ‰(`)3SÚ˜èç¹1›É+-:%ô8p'?, ó\üú‡%ᔀ^Ă‚úH½"È4Ÿ)ÂM¡ñ©úP¨9%7¹Hiè/ü!©¯ Gó«dLºâ!n&{„ÁÈë•|Ú̉öÍ J™Mø̃c_u|Ç_!r· endstream endobj 797 0 obj << /Length1 1460 /Length2 6185 /Length3 0 /Length 7176 /Filter /FlateDecode >> stream xÚwT“[Ó5̉¤X¥IP@„̃{¯̉Ej! I¤ƒ ½÷^¥+½Pª€(U¥#Ẻ;_Pï½ï}ÿ­ï[Y+yÎ=sfÎ́9ë ;ë}}^9”5L…Äñ‚ù@â--50 đ@ǘ́pöNÁnĂ`á(¤ø000)Bpx¢ P„€`aq°ˆ8àÄ₫"¢0âEˆ Ü ÅPG!aX vÚ·³Çá÷ùëÀ å€ÅÄDîưrÈ9Á0p( Đ‚à́aNø¡@…Ăpîÿ Á)iĂ¡Å@WWW>ˆ–…±“æºp…ắz0, ă³œ— І8Á₫”ÆGÁ0°‡côQ¶8WÀ8†Äâ]!m`~w€¾&@ C₫&k₫&Üü9˜üw¸?̃çàÈ_Î(儆 ƯáH;€-è(ḳáÜp÷¤Í9‚À¢đ₫±Æ~¥(Ëé ø ÿÔ‡…bàh– Gœ×<ƒ?f%¤ÊÉ †Äa)ÎóS„c`Pü¹»ÿ4׉rEz₫µ²…#mlÏ˰y„"áÎ`j8xˆầ†DED…0g̀ j<ßÀÀ ûeŸĂø¼=Ñ(4À_̀n ĂÿPxb!.0óæíùŸ†¯(À`€ XẮàH¢ăa˜íï5¾ÿ¸À„—:ÿüưdW˜ ‰pÿ‡₫«Å@-uU=-?%ÿm”—G¹ ¸́O)7¼¬û̉s±Àd×ÓCđ4w«µUc¹"Iá1W3å•–ÿôp |S M­Pđpußơªp›7×́qBx—y´8 }›û@°d=[k ˆ¼É×z»lr¡3dçV)aŒ A±vNÉá¶ƯÛnT …K±_ÄáºÇÉ:a@›]ëẠü₫u £á6;áÜ.JBéO÷Î~J7'ëøª :ÉNôêÇ›¸i{=[yréiĨçá–̃i%,êÈ^µ÷æ½6Éuù ­n¯ÿj\tD‹ÜÜvSv8×Hăè·K-ÅR~d|bϾd¬o Ø12leH]a1mµd9³>CY^ÿ!Ïd”?{Øư¤ÿbư¦ñm–oô„‹ơ™é¯ç ›«¨‡ÊXX®€„|ö ₫Í&×íe#ª̉;̃;?È&3c»L¯´|«­;<,÷·+¾BÚ¶nmÊPñ²jµ,²~̀ơÊƠÄjÊrHøQư€@Ä}ßâZ=½~C`.Écoô)ïđí¸r4nIÑňô0ZƯZAêm͵1[FÂd+j¸ =¼’bá| b\Q=©ẹ́AúQ³XwÑÑ9÷,"¬ẳ~xô7‘A(û-åIÖ®‘ĐLu‚7x†&¨G.\ưj\WÍ߇Fe(e”„µºI÷Ù~P­94e17PÚ}å¦×æä9¢\\¤[¤¥PM#D=LÅ¡«·³Ó3UYö¦ülêYë}%lsó ®~¿·pèB{ªÍ=5.ÁăñîúÅ4—7̣uGf]»¤!ÎƯÖÂKàHµĂ¦A *@Øû±½X©5Û¦zÉÇQ#lˆƯvËm'6sªT±̃Nÿœ¥Í₫Ç S)ïîƒ=ßû]c Eæ„Fe)OxZ¼h±% úü-§̀3Tsx#¤½¢ïA¦ØB_áÜá̃÷ºYi¿k‹µ9{Qßơ\ÓFæÅ)‚o¥Ă6(€›ä¡Í+̀L¯n̉¹}k¼âŒ[xëß|[ÄwÓ0g{èƯN³<”ÀU$J¬¯7̣ Ñưd¶–ß!QÇ¢ẽ¿™½ưR´afsàœ§ôh$0§´â™‚jv 4È^êư=yĂæ‹§= tMØE WŲ0Ưm›+Dk¸ÉÅœl[ ú\@‚©ÚO¾«Ivtt«g{çÑĐí2 èê²%Ŷôñ›cÔT>7ÓµÆ7ư‡îù¾Ÿî ¯‘²¥2A }«}3…tù ˆß̀l`́•4Q̣ïŸAÔè+‰„9-1Z·÷Cq6¾¾₫Óϵ׃øÍ¡pÈü®àÖ™Ôó[Lê ÷É { îWªŸª¼̀¶?„º^«cĐZϸÇ]׿"äÍ÷¼@¬đFeömaHK-ơ˜Éjw ‘đ3~o ĐwK£JºÁ'€EÂí>ư¡ MGù¸îSÄwi׸™k’ŸUM"+»‰Ư\h^^óö]TæeK¿nMËÊYçᨨ«g“¨é¹²êߨ™éH¹¨M¿+X6B*xº=[3uæ Çne7¬û¼ªœ³đ‹D¿_¥îeC–´ơÊ[Y‰ư1Ø*‡²)g8EîqàÀA¡̀àÍH AØ·”–fËị́À‹Ôö:dÆ3ï ³‹€¦÷b#qåB;—̃ Ô}$÷«âƠ41zøÜú«àƒ,ÓĐ£:i¥QÇjßjÖ]í1­ơûO{b “+wÓZÁˆCU¦^äđ©{z'̀°»û́(G<•† `ô2gT˜§..3z4ùMk—s$2$¨Œ‚eë‚ø€b„=CjÖ̃){$°¶ú~j!>Ø »9Ïå0“»ST»zW=QUÖp³NZ':ÆW›T¹£Ü̃×;”Ov˫֙Bdæ^Ç…¼!Óœe´̣D½₫Ö)K/£#$0Ç”ÎcjÀ6¥Ê—&ùƒ­÷´©-½¡ À{ËÏgåTñÎÏËëu8IÚ̀x²FĐßÊZWï PåbÂèîÆÔ1ë íæ=6¸i­é ”r¤ùzsOJ×5WçT„Nè8ä£xâ‡{¹†–t÷ebëzúnh+”/ëkíÁ7Æ.OH'^¡î~·²tié§÷‡;Æ™k¢+ál›#^›Y¬ Êa³}a§ «ñ–)lt“ÔƠØê›“:Lz9?̃¤s̉s^¹¶—§nz3ÎÇvœH́^R‰pÍç–àĂ¼Wå‹ơgLú÷HdÀÑ2₫d”[ăr£]³îÎ' ̃á^ä°mÆĐ|ÿºB̃N_â$;̀Mwc@+3©ÔDX`¬cÇ;‘4₫*âj¥ê*zùæˆ*é­Ûdfù'¯©€Ă#·”ŒH<3Á¡[àƒªD#Í“a!wc /ßá­…ä^ơ¸‹ụ̀6«FRåŸ&Ú ÆƠ}Z–M«[ëNǬN\rNÑHŒ¿á%-#ăçé»|_®™đâVRSV+˪ù=2Ç~ÆSHê ăÀuˆÎi«ÖiËaÙÍjëtC̀–\™S·F-aTJWôq— ¡B_ß*̀ˆ?Au Qơ¸i*¾m“K «|̉¥]Èü^  ₫-öÛm™_‘3éÉ2§zbùüƯĐ³́åO-‘₫Ÿù03d•D·¶”LŸñ•4|Ư¹²â_́çñ2i)SNrumn˜­@₫9¥&!0,æ‹x£<Ư`|懯 cÖđ ø‘0ÈkåG·è•ÖÏYE'˜=[ĹúC¾ú„—Ú±åESVw’cÁüöÑ [åNáÓ²3–ùrw—?´?li§!»Ç¦#wU4%*‹lDûôÿ(ÿJIú`*^îDÔIÎăÓΗ b›Vm‰Û‹©>7I‡â[ѳ-»É×éT ¯øÆk¿Ï®Œêœơ’h\ü.LƠ.7»7ÚceµØê ¤$¼Ađ°&Ú÷́Ô°ûP˜Ñ́ăV½ụ̈|üD¬dßÚ̉ư64‘C™o{÷ªk.^</ÏW>Ơp< xiXĐƠÿ»b̉œéèKaö§ª°vq£ïàV*Bq~ đ¢Üë\¸”JT*ù´‚±uíƯ‰×k>Ïdhe0b•ÂYD7ñX,…çû[¦F¦OOÑlŸT¢«µlJÏă”U#¸fòä ”âfơ–àé6»›#ë‰Bª¸¯ØêËÃ̃>C²_¾•¾¾Ü¯"ƠiQbÿq˱"½ N.j=»/‹µ¸±ï¦rÆDvuư¦Î^PÚĂđï Ê´S-ï/ßcƒlø3èMVbmjọ́?9ùBÁ¨*åÇdÁ˳ľ¯”Ö‚­7Âï)”;oup<¸¶®–—̃=BŒyi6YÿúÉ›³ÏGz0”•KÜ|3ÆæZæë»Ṇ̃ Û1…Áë¤UÏÆ›ŒIvÑA£[¤¹₫ƒ½r9,TœŸ̀µé?P_%§¢Ư±đ+ÓI¬BL¿{ï.Å´]lá!¤áGïÁvú¤úmÔ暴~)÷ƒĐ¾ƒ¥ |bE¢₫6₫Ô1¼¥i@EÉ~”cEæº ïÚ\9£Ub悬X8k ÊLV3bl®‡£üzƠ£­â.÷«=C‰ ^¥!†¥ÀxÔ ëÏÓmB‹ mÇ/ùZ¥K¾j¸9 t̀½±Ä1—¥¯Æ¼÷2₫ÀÊZV•­hNàÛà·˜ĂÔˆgs2«J—ÂV&îL׌JT́}́ùđ4ÀÛÉ8c•÷gּܠÖ kí“ñé¤Û(Kkm&g-(‡´\Ơ‰Sz]’Œø>co¦be}arK4?­sf³×ÂPàZ…sZíèÎÆÂ–Éí’3—¶đƇSj‚H™”́Ă©~9摆e!¾b¬x«y£„*yàËjD[m5”–fñ”à~Á̃6+Œ,orúdöÄZK%ÆO8—’xˆrGTẩă§›µg[Xbæl‹µJ);…¹±µ~Ó2+ë<.JDZÇ·`|đÿUă+B¸cÊ­a…g"*vQM)oůÈK‰±í\üÙ³~“-»A8vç°×su‡ƠŸœV*±̉Åwظ‹¯ØÆgO夔2?HN?# ^¬/ˆtƒW†=w¾;ĐXQ’PF5₫b—¯}ÁƠƯ|vÜ,c ËḯôưT&‹ïcFưᮄçÎA“ઠö́×ÑEÚ¹£Ts¤­ës6sn¯Ố•¤zü‹B ̀ằ1ƒ¸vïËÍßƠ}K矦/¿s¹ ˜8ơt­Ë”¼2™b,úèĽÉPÏÏq(ÿFR×ÊX̣Ö¯-(À«åÁưÑ£—]œ«3CkN./£:´qÜÙ?Ó T©U q”–8ÇÑ̃ồ5Afö¢¢zåâƒTúKûÓߪ.Ééds–aߨV±sN¡'Uoós¤đ¢Ă(56|*C­¶X¥)mé®&$“q®+JJÔ8Tvö5Î~R[:àÇ̉2çÖÏÉƠÚ©Ä¿ƠÖï ƒvó7ÀĐđM/ˆŒ)DY(Èç̀‡¯T̉JMcb†¬’6i3ÎeœüæÓm©Ú0ÆL•P óW™¢a48iï'¥EdÊæÚëÔV÷}ôÏX¤4¦Ïd”–5ÓÓ9jx¶Bó0flüäl¦"€năhV‚ơÏ&†OKưIê¸ ­r0€g{r”eñ†¢Ư=]¨n4öÓÁe¥‚]„c‘µ,R—gk@B/6™Êï₫.¨‚.àS½÷­+«5Œ ü2̀Gd%¢•Ä[]û2³†è” 4”ñÙ¥Rj;«¡Eê=V?̃$<à̉sÛ˜‰[!êt#â›°/¾CÖ¬¨J¿–ư ÔK­óyƠD§^pi!¨qĂ¯@Ü™˜®»×̃]cºöTYB̉ä,û}à±O‡×fIĂ,ù(ơµm ¦í¤¥bC®Óz­¥'¯öhQÊđØ¥A|°_âï+h j˜ƠOo.Ë(Ưù©‡̃K¼½6ïxg:{;NV?çĐK’ël[ƠŒ˜‘”Öû^°‹¡Œ¢$—ỏ†y~úI₫÷Ä?âJ?Ϭª¼ï¡~OBĐfÀ¶¢¦µ;ïN&J'Ôböªlh»“-e%̀ĐMBH‹»|mPÔ±ïµ]t2.´¼g9Ḳrå¢V³»ZÖ‡@¼ ƯØ—¼|ê™èÛ½r²Ëî²/¿Ñ}y$% $lOBw£qC ”n”‰[;<tÜ"ơªï,÷u%·o‚]°:¾M₫j&Ç„’m`“T£ªümÑ"KÎîzĂ’=·æƯ(¥¶y3\BˆŨÑzW4}÷€¦nW¼ăå‚₫t2Ÿå,ƠLKZ0¶ vá3(¬ºÚÆV6đV2ÿÙ"đt¶HŸ‰C«Ñ=2ÏD!?Üú`¡±0’‡\ÎơºFÅ̃KSYly’đ"3Â,I*xº¯ƠgÉ`n’ês7Å¥‚ùHF×Âa.đ}V₫|ÂăW”)^¼•PM*â€íZbếï>½ÔÔ„gŒ‡ A"£e*<Ûû³å#ªfĂÚÖ¤ɸ9ü DJD}ÇÜIënC$¾e¹^ÏRƯơ²Ñ^ư¨¡đUS.§Cä™ơ7”.‚ñt8DÓB4lTÖ¾ÅJ5»”ö€‡ö²p³D+Óûo&ówLÖP?ö@ ù÷L•ÔØ”Q)=?êăè }̣‘´»(ÿ±fŸ ¨vwlaBßJáÁg˜AZ>]‘¤u%«n˜®ÄëX1 ÿäÓqcs‹sûBư3jÿA#}Ni¿¨† ­åwP «ß8jÛ£ĐØÿÇ@?\¼‡Ô¸…g“8Y£¦¥íxÜ€ØơË3¬s°Ai«ưàÄÚ¦f<‡¸±IXgKj,`Áîy~¦tDh0¡ÆÅô˲GcfßơµÅEŸæÑƯµ#^-œ%3”™áZƠ³f:@E4ø¦¬H‡ _^è́ñáJ!׉£(yÖóÀUè-đvÿ¼—cj1'Œ xsF½¤U…²q.₫VÏΫ,&Öê=zÈ`•½ssé¯^§t÷à!ùpñ×^~¡û–•f/5>¡G¯¬tïçí?á²úù,YW·§~•óøâ`¼ĐÍÄ‹"ÿ™€'´Z³¨f2!n+™·zÊZÅ—ç:|OḈ¢ÖĐí¶³„H¢S‚V¡nđU›̉ü¦Øoë4¦îÎäµ̣íơl²wéCú„WY×ç(c•®×w«5mïß;R3xÅy:è₫)ø{üƠ$4¼iù̀jŸe~Á19ûT¹cZ¼é5•N₫*Û̃02VEñb‚pj‚@v.‹´› éZnñ'½=·-5“e˜^ÛĐpƒ6øÍEÜ8¿6 ¢)Ëï‹¶p3ñ»1gaû­%w¢j̀5uƒ@Üûơß?đ4ÈJĂøx'PÏG¢WNèËé¯'=íöEôQmt™ùĐëñ\gsé@%)¤NØÍ’ºû¬å¬@XB.}QÔFbV¸7vË=rÊí÷ư?í›úqvq·Ÿ-;ó•‡÷í3·M¿/¾Ñ9X°̃ƒH0rØ1È|~i—]ÓÚƒÔZßc¤V%3¦ÿépîêuŸOḱ(üº¤,ă-¼îĂpu°ËEmOÏuö ^Óˆ…,̃́&>”,Ó4I½…æå¬ ^Ô…ĐhÍ—̃mƠ$­¸§V—Æ>ÜZzy°§'z²3§‰…µ¹uPoº¨h“`´TM÷>*%ûºó€cFZj-Üß½ñâ)ZF†´*;Ṇ̃%<½]ÄYD½œâöô>® ê’8Àµ>ǹïƠ¿c?~lhs—/1Ăb›1îÓuŸçóü‚Ă™]nJÇœƒÚpË QÑD¨BØ]ƒ±>â¥ÉnÆ^l©ú́D₫ü&5üÍDô g†v›ÿÆü²»âײ;ÔVÖxØ‹·§¹¼8 {’ùøO[ É oIËI{ƒ̃­]«‘pyçYà]ïbx̀ßŬ:àµÿîÔlf5…Z±9j‚^Ëç̀ekUÍ*‘wÍ Ñµ–÷!!91Ô_¶„ỐgCAÅ‹;XcYÔ½jç=Èf?ƒĐ ³¦¬V1Wc±bƯ« A=@¤×/¼ËB‰n’îPjÊä«É c¿Đl†M̃¿«-ñØư“¬[àe1đáÆ =úq•ÑVæCÍWÅø³¡]£˜ÏâÚ‡d_#8-½)”ç7û×O‚JĐnöVë¶fZ_~Âr“TŒƒuB~: Ă¾]/§‰ç¥93ѧ³ztbñª²¼¢Ư¢)ä$§©û¿öé endstream endobj 799 0 obj << /Length1 1478 /Length2 6403 /Length3 0 /Length 7390 /Filter /FlateDecode >> stream xÚtTÔƯÖ>H—( ’R3tww‡äŒ30 ’/!̉­0‚4̉¡€t—´̉ t|c¼÷̃÷₫ÿk}ßµ~sγắḉgVc~E'„D Gñƒ€Re]# BÄ&P ̣&æ0ƒ =¡¸Ô8(#!`S£0~º8@Ë  @bR q)  J₫íˆ@JTÀ̃P'€®@ ‡xs(#ÜưPW昿—nGHRRœïW8@Ñ ‚„:‚á]0Êâ†9Ñ #¡”ß?Rp˸¢PîR‚‚>>>`7ỎE‡àE¹Œ ¤7Ä đ“0@́ùÍL€˜`â ơü#œQ>`$€`PGÜáw‚ ˜ĂÆ:}wü·³Îo>ÀŸ»€@ÿJ÷'úg"(üW0ØÑáæ†ûAá.g( ĐWÓ@ù¢ø`¸ÓOG0̀‰{ƒ¡0°ÆáWå`€¢!Œ!ø‡§#ệđ„Â~Rü™s˪p'e„›̣$₫YŸ  qÄ\»ŸàïÎ>„#|à6ÎP¸“óON^p¨‡DSå "₫7æAD@ ¸¤0â€ø:º ₫Loâçùeư„1 ‚Üîg HÔ‚ù#đ{C(¤$(à? ÿ܃@'¨# àq‰ÿCœï1ÍGB}V@Œö@àÏß¿V6y9!à0¿»ÿꯠ±¾±‰‘!ïoÆÿ²))!|ü"@¿(ú)2q̀"èŸi ÀĐ?eüG¬&Üü]-æ₫®Øû¸ÿ àŸ¹ôƠBÜÿ¹5Pèˆù€₫ÏRỵ̈ÿSøÏ,ÿ›Èÿ» 5/́—™û—ưÿ1ƒƯ 0¿?Ñz¡0 ‹ÀŒü¿]Í!¿‡Vâơrûo«& ŒE¸ ́_×ơTƒúBœ  (G×ßjù›₫œ21@xB>+~Lk₫ˆ-LJ˜§Ă#É_&fr₫y¤*ÜáôsÄ„DÅ`$́GŒi2f' afÑ âûKÄA8… `èœH⟕`LJ̀ëçŒúiü ÿ ÿƯÁ¿ b˜ˆ‡¦Q#e ºcø?ˆ€₫ ÿ Áäu‡yy₫₫ÁÄÑ ‰ñFử†æßû_/â q$G8J‡?¨ o´¦ Wá”n§öW™¨À)›I•Âvú·! 4ư¨ ªl̉?áÆ"͸5÷„#cmç®]SoÙ₫ƒ̉c““¼»₫‹XíĂưˬŸ†–Ù`¥Ö¯E:j̉¢q©8°DNÖ‰å´ĂY+ç˜ÚySŪiÆôÑ.ÈÂVO®̉]‚&a •ÜÀ–  ˜+c^§—êz<9ëÁ’¦ÂKB­l™§uå<Ơ™ˆYëKlöùhÓoDƒkbϳ‡}Ơs áƯ%w̉bèW åăϲX'†ˆu„°h+¬²̉n_. æas°xLè¸q;–kYfŒ‹ª§2!e߈̉@X5—5œ_ªâ6×íÅ«AÅ›ZäåxS•ÊZXZ(4g{€8₫S± ⻡fƒíƒ-›căcw’c‹?̃T›pñaS}–à³oÍX~0”XxAB2dÿè½L&3XH˜z-ÓđƠm·ªæt2c¾×uo>'|¡ôkauơÛ·ẹ́½ôọ̈‡â)›4$v}9xVÏ›%| dD@cL‡²¨Ï'XÓäd̉b©uµAHm/ĐWáó4Se, }ZÂÖ¦%WÁ4SJ0Wb Z7ăy;kÜ3¥çËƯ ½kDASKSØÔ ߃n2ÈØh̉Á ñ=Á}Egg5`a}›¶ûđ»aN9™‰Áơï°œSbÈG¾$÷«i†0d°ḳYm²Í₫Óđ8{^Xá1Äđxü©‚3­˜0ƒÆ‚Ø{ÈŸ̃´ŸÚîmv?U×ưó=ôJwÏx¨â‚=+£J_åI'[*+ó£•i^qwë_z Ë%ubÛ9QƠ²₫Ùdj Æl»Ùºơêă/{_C¸™Ia5”C; ûY /C/̃å)¶³C9é=¾`ÿ̃ª!bDCùB/Nđ¥çăÛă=ôæ 5ßÏ;£/.Wn‰ñƠ¾f~?ª§oe²ÙÜơD÷âµ»÷A+Y&SdbêÑdg‘RỊ/vjx­¥r©2謅vR¸{\$5øP/j4Vû-vΈt~Ë·ÑdX¨Ú7>Édœ̃à+léÅ/…NWoÚ籓Jo],ÜkŒ‘éz•û|¹“2œăỤ̀JR¦Z=LYƠ>ẤkëbSoµạ€Z! ©cièvX0;úiÛ°pă±ä„äÖưxOÉ(l.ûåRf²-ä´ù©”̃³Â­Ï‘ƯÏjXđĂH3l™̀ç"8…D|(a₫$ḱ£Bæ»”•>s][ú’×ù«lú¯²)?ö›·ßS£°™|eï‡3¬ î}fmø¼íÚ=ô,Ô„f?~ĂVpäd—¯kVìạN¯^[<¡œ×(u|Ë Y˜~Ñcù£“rÛ̉ÔX1ÉHZ{S¬Ä„'â«jD– ~Æ6ö#²o¤–ÂJă_ß$±¤dz³O7jbÔ=&[8Û)V][E?v>1đ шȡüF`~Q%=£ÎT4U&ܘaûÓÛÖ}…äRºL¢4đ›ª~ªTÅ`ǘȯ0„9v•.÷A>«æơƯû‰A¸eÀƒ{á@Ø o¦2ûz.MXÎeđbëjƠE[Ị̈đUË_îʸƒ7lIB']7ơâØgÖ́¤/»Ÿœ‘–JxùͲ#RæŸ{;9z´ó¶ú=b½œ³Ë<»s̉²uÓ”¯»•Ă³•̉8ÈiÖè˜á.³ƒè‡~eR3k¾̣ħ‘{ăµ±ØÁ¯.ưe¿Ă?,+"]ă¾5G‚é¶÷d 3Ù ÿ²-Ưâ'¥x?=“¥Ú÷²te›‹̣nTZI'4ü#ÂáÇLĐå …Ù§¡ÎŸĂ.Ö l¦ÿ¸ôæ év àê7^nSi蛂ù]°Đ‰'Óä‘Z₫W~WÚéöµÚö}¹º—¨z:ÁIơèƠ99J0n”äj1¾oixQä¯ P)<Úî\E.ÈŸwÍí"éÊÎtVÔ‰m£°«{j?i;\§®}$-Z‚_àÓ½Ù€»¢‰ôØU,vV|¼`yêơ&¤mn¥ư ihwk˜Âyë+“Ê#©„øi'f£Bœ9@²"ê6é&?ú)ÏR=]Đ[ïºôỶjôµ×5¡ñ:¤v}øííb°ûKọ{ư0«¥¾±w<ºẶưp5¹S®ÜƠyÖlq¬ tenaOôWY¢4ưÜöÔ§Á2·ẹ́Í}©ƯơÏ Ơ°à)HËnl{¯… ¸o¶X¨Çg£7ª̉ºl§Åî́fù Ûƒ÷r)^ơÅX•ÄܲnîSÍÊoóahÅÛ3ß!Íơ_ƒè€Ăi)‚||»̃«p³ỐK¾¶k₫ uåùä%~ïfÀÍr˜üưbÿĂØç)båj×%¶YÜùu†8{̣ÏqvµíåöUEmö)y;sz=Ṇ̃ỡŸºl­/₫º—D=~iøñK‘ƒsïLcó|x‚(~êµ)Q£ÿĐ¡Ë7—~đÊ“§^Uj9C©2í”g~sµè7ƒ7Îî5̃èq9º‘·²i{*R¤‘ÖŸ—>qfÛ:è¡ATf¼4Ư>|Dz\˜”4(.·ÅÓUp˜ªu£¾¨TQœík€J¤‘Œ êR·³ûû©çê«ó‡’ß“œó‹3†p–®?_óRN½²PƯzr«GàÛÖ–Áv¶{Z3Æâ7[¦-™Ë 7đv̀1qO)nh‘̣–¬E¨k ¤˜¦ư‘¢—»Ê.æ]ì`byû¯»3te:/®E^ï¬Ë§c}æ:Ú:n? V£u2S×çă]§ñ¤~£~U°h+X[́QƠÛ{„í×I₫æôô>óÿp•b”©đ1„"-={CwRA«ưnc´ÜơD^ïơ£/Åm3­±ÀơơäAC¯•‘1=´]&==$Ît—7^æ'=3’Æ‹aiÔ>¹;h’SsSíø̀zạ́Øv4‡‰‡D:•¨%đ›@źă1™†×¨ØµaçåàK®LCáiß»µOX„YŒû¤ĐnoÏpÔ¢´ å>æê_ïd0!ÍæCÛè}m̃Öá7Êñ,íf·VÛ„À2OqDÍ·¬ÖsƠ¤oñéqqQB‹c¬+ô [54Fû¿²´È›Hm+Lªí̉®ë]“[´Î+d̃đ4¸.ă‡6‰8ש©Ô¸&̀L¾3¹ÁckŒ7ÄÏ÷ ºä#‰¾¯W«J=¨Œư½ü˜Ä’$̃Ríß6z´'Ü8lMü~µ}ueùEÔ>Ví‘]ºok|iV`,—ERuwT¸º¹éø-1Mk–ÔđơÙ#¹ ©^3»ó½rc¯$ïiƒhFª­Ù&© w…M§ư»ö{½VÔ2œqú¦ "~,}äQ}-A₫øÂ´0ằ‡§lÏ…2æµÇ¨Ô¢Óƒ»…uå³ÔÑ®Ư$…2₫:…$bmuñ„e¶̉@ĂÁ¨kè³UÀưÏÀˆÇAù:cUÆ”1…R!Îè1·Æ×m» ă{Æ$B²ô‰ăVïœj&“/´2¬gßÑ0—2Đ8nMÓ…\œ’âB5? u¥+®#¯b¨ËZ†Ê®èû´¼Ûø´Y±‰ª">?7›ú4ƒøåEºax•Ớ¼Œi«…#îăéyG̃#Å ¢m½†Y%cQÉÈ“°ÖwØñè,¶öñŒw.&_çVlÍ; ñg¸+ï±â|đßœlđPÇÄ%/GØRé±"KÛ-ư e #9i‘/¤4•ïØ F‡ó?`‹ù[‚÷]Ædh‹0ÜëƠæ§Ÿ˜3/4^5ˆí/SD«s…uĐt̀ѾîSƯÔ0o¥-g̃¶\1ïå¯Të+µmˆRjóYtë̀;&ÏUåi¦9]ßW ¯ßÀ'+›wbà;#é{¾|U¤qṔ”vâ_h6¼¾‚”–.‰Ö~/Ʊ­V °I×âRwÉÂu:Î4´Pñ¾4lת£jsí‰̉Ù^ơ¸&̣±\?ơu‡?·F£,’ÛRÓnÑ•PÑKJơ “HħƯóüè>§Ă‘̀G¥´jưÂúØ€§ÑÏ£ùÄ}_O*Fƒ!ÎÂÏ÷|=]/²b‡Ôñ–Öù•÷:t9¯—Mùó9•hN64c'¶Ë…Èi^ŸqKÄêGcJnhTÍä÷ Å[ưüóà“Qơ5“đêf¦B·<đ·Äb]¯i•IÔM3A9‚]́±Ă‚î»5c¢Ÿ{Ô,măà_ñ^ụ́»s[³D’Â.7[*É\xcÜ’PûŒ¤³¶r¡±DCË3ä_óUµéă¢ư/®q™_®j;vëÏó‰4?‡Ī7|<¹lä½·XŒ¥=Àpé7Đm0©eă_}2Ăơ)w¨b\;ǦZ+-iCÜ—h¨÷ƒ°¬g·@¶fi/ºs°¼n«NÊé̃äæ‹N¥0›ù«cî¢ål'ÿ2Â*œ_ Ú¹¨ưwúåtGërc °Må.F‰‡áR‚çFÉ8›̃3ñTÜ7.‰NÄeÈyÖ,Ay RpJ—R9̀ä«êlÑ0¤‹GràƠÔ¥“ +£øVÄëÆv­4I¬@”opw:-¦eº.‚­̉găễăϩʥXäưê{Ö…ÙX6¼¹&­Çđ÷CÉZUFê¦eè> stream xÚxT“Û̉6̉EªH/¤×@¤Kï½wC ĐAzé M¤#té‚4A€ô& ~QϹ÷ûÿk}ßÊZÉ»Ÿyfö̀gv²ÂÉf`,¨è€´‡ª!hA! 4@YרRAB@ ( '§ ‡₫“pA=Q0$Bú?ÊP0‹©€ÑX¢.Đ̣‚D@qi i  JưMDzJTÀ̃0€®@ ‰€¢H8•‘î~0'g4vŸ¿<^€ˆ””„Àow€¢Ô#º`´3Ô »# #!0(Úï!xî9£Ñî̉ÂÂ>>>B`7”̉ÓIWàC;Œ (¨§7Ôđ«d€Ø úWiB$œgêÁéˆö{BXƒ@(¬‹Âê Àî0ÖÔè»CÈ:€¿ "$̣¯pyÿ CüvC H7w0†p8ÂàP€¾Ú-#~ÁpëöĂà`{,áwê`€¢!Œ­đ¯úPO˜;%„‚ÁƠ(ü+ ö˜UÊH77("ù•Ÿ ̀ Á»Ÿđ_ÍuE }¯aÇ_e8x¹ ›"`^PM•¿8Xˆäߘ J‰‹‹‰ ¨/ÄYø×&~îĐ߯ß0¶† w¤;À[4æÅ~ À̃PÚÓ đŸ†®HDD0`u‚!H₫ Cÿ¬±ư÷„ù¬Xù‰€¿^ÿz²Á*̀‰€ûư›₫»ÅÂÚZÚæü•ü/£’̉ (*”DDDÄb€ Æ1Ă₫Êă?|5H€ÔŸt±çôwỄi€ç¯áü3–«\(€çßB¿B°o"ÿg¹ÿvùÿ©üW”ÿUèÿ‘₫ÛÎó‡đÿØÁn0¸ß_ ¬r½ĐØ)ĐEbgñßTsèŸÑƠ…:À¼Ü₫Ûª‰c§Aá„U´ È]!àƯ?8 ¥ó…:ÀĐç?ªùƒ›₫78 5@¢`¿n¬ø_6́A\±· +Íß&(v†₫¹¯*‚tø5l¢bâ°§'ØÛḱJ  ‚J¨ïo1„…H4Ö€­1àˆô$ùƠX ŒơBúüiÖöÆn' …CÍÙ¿0Q,ÇæơđÂvëo ºÁ^¨Ó°€ sÇfø ûGº/OOl̀ߺÂỌ̈÷ú÷E…úB!$³ÓHˆL„Ë«ˆÖóE&ÁÏĂ„KËí±I–½1bh®Ïœuˆ²Ơ'<”8TÑ=1˜)ŸdâÛ;ñ½ß™º˜¡‘ÆQí]U:,øvÜéeu@2:J<‰]¥ÚO6d¡x`oÍj>})ÑÚx¹^tÙÚ°’Ú¸JN)Ù2˜ĐóÚ·qY²q,£-ïS&Üô´Îô2Ñ4½Ä}K8Sjgøæ·j5øñăÛܾ̃' £Bíîjñª(j†[₫ZlyC)ư 4ɹZ¯Q8\Jb§ÊåéÍ ÅnQ\‹x$Löµ$÷ƒ¼êô”Coè?|×à…AMËæu-1Û­å˜|&£oL‰u¨y¡ÄYí€s:˜¹_ ‚çwăÓ²1íó?u'‘¥eg–:¸s ñDĂA¶ëcôçg'‹ˆÚ¤ËÂ%û?=W7€³º9Ï]ÜKP3rRhâé±¹,{ Ưúú¼Viq;q²Ùø¶u°+úɱÇB3dÑ–½Ư³•üZŚô=•Ÿª8ºVû²Ă71/q2Ø(?ß ¥]]ÆJAjfŒ=Ñ DQ`BơÁDg'Sﺥt¤bÈ$%9µë^9Ë˹âïɆ5ʦK†Î\S1ÜI¤¬]½aØơÀ6É̃ó@X”ØV;¿ƯÊùA©·ún¬a;ébSÉr"ô@bz1_éÊ4غ́áư|ÇÇ?¾nœÔïç[(bb¬à±iÁ«vÏß±´Yơ%0g¾ÛénăNßđƠ¨ÿ~@m?¨.ƯÏQ ¯lHkV₫ØGkjƯÖi=i$ö́zçØp̣TÄúLæîZ¨»íf½̃¾û %ÀM î™H)Đj•n—T>iŒY° ÙWÉ›dà±ú0Ñi„³cÉ\^{¶pÛăQc滺ûÁi7óGêæZfa­~È^q˜äoĐÂ'a }ñ·~ÈÚ½‡Û6æL*aºM„1–w—J£© -§̃Z¨è\®Ú‰6Ư¨j*Gj¤ˆĐùN0ÜØâîhơblA’Ÿ~7×»Íb”­vT²›Ơ”8‰{̣ƒ+m5~[í'íư`*\#g‘—¬jyö‡%U£AüÑp2ås@Iñ|q³·ă2œßq”>Ww{÷6&è .Ï á[Œaß«² 6z±nSáµFùV¡]¡?0‘À¦y#₫Ơä«ô_¨®́Đ“æ2Yï3û½xîT ù̃•RÕ0}–¸úơ«aôY­ —̃~,é‹ÿ‚‰¨h¢a®XÖUµ"ƒa›3[»"Sn¼n†Ä<™÷nÎÛI‘ï¤Ư–IË­•Zˆè[-­l¿Ï^ù­!=›nÜh—ÀÛH9}¦?×PÅ™„|RÁN ¯Ÿv(—¢Íơ&íc{Gø†¢æ¹-n&Ëg6›ºÄAs@Ăß•r ÷ư‘Ä7ºc U-̉­»â¾Ïâ#— öÀ³c#Ü9û₫zdfṣ>²%̀öÇk®øÏÇG6T’đôĵר&®ˆˆNᤕ[̃l6“Ï=!`²cÜå{³c˜eÚĐ6cö™ÄÍô /[ăXE±£,q%YªùBoÄ|–É*qUVbíh+{äøY9µ0á°`pP@̀x߀B₫dÿ#ælùµËrxÄ10¿Z7ùi* ‚L¯< gß™ơ­âËA§éĂ²^mØÚçfsk#ưáạ̀l›“Mù)RÜƯ#{t<5Ó™R<ù§~Œw—])¡Ñ—w©$c€-Á.›¡ûÙơÎ$¦³&Oñ³ÖN™bŒUÆfGß÷ «”+©Um½FŸ» £ÊÀ‡U@ª Ă®Hî˜ôQ„Í‹9ö₫êỆ́œaĐÅ>l›µĂ⇠69Ö_7Iÿl{Ï;Đ– zgf³ØûE÷ç&Á¦̉·¢8ÂL½ÎĂ„ èÙ¦ø™:R·¡Èj« ÆBrÉÑ7'³!CÇơ£È[³¸/ârt4ß7k/œ7äñf~%̣Èăÿ0±ôKïn)ÎϹFBm§û.₫̣ †xÓŒđ’‰û$w´v́´m\6PDá ÿ±Ö‚Ÿ'Ü2<²ç̀Uϼ̣̃Í®Ú̀½M¥ LÆẀ|7Ñ’Ñ.ÏÜÔ¨­è '%WñârÇ-¢'~„â <Đ-9ùv§ü.ƒáçfªˆ¿§Ô©‰s̃·oîó?L*ÊgíIS­‡$¼5‹—¢Û·ưA¸ê”…v=‰w¡Í5P®ûâ­··Á®.DZ²C¶G”ŸgS/R H—ô&>?p£†g­Élêp)N½́\"LÛ‘Éü–ÿ¢g¾Ư®́uöî»CQº€úîôÚ¨}áLìÿ„N·UD`S¬Ê5Ö¾»‚ß–ª»î qŒVÆßû—£_Ç`̃.3̀4*®¥5u¶¡áíµ#—Ö8&¡¾¨ƯB–HƒX¾ºgPhyb‰cI;ë\4=빆¯qY"ŒưñX÷~eæ*´®²ÛLÖqóf¬ÿñ†d_o`G±œĂO?“́Ç¡ƯơfnưëO–'Ï—çS»óÄ!ú°™`£\!Çq…§vƯ߉m,†ï9²g’À%î½ ̃ĐƯáâá*ä‘db¯¶¡ÓÇÇî¹|"¶ÔäaBÓq1OGº¶kIùb¼ưyqîFv !³á¼µ#Ä^̣ ©¥Üî¥áks0ăû›Ó̃ÖA""T ®˜ŸEx"óÄđK̃ĂuæB“‚]œ’SíüB×ÊÊwq.ƒ+ ‰™@º ơ—,Ë·=b_'nƒËÍ ¿púGL̉k½j±(b,́¡5ư€=íÏ…đ'ïÄöZ§̃)b W¹£ú>,ÅƯ½Z¯²́kíb¦÷¾§₫¤ĂBq£ˆjÏQ*œ¯iÇBúkû†\k¶4ßđ¢‹#îđcn©.p‹ ?KM 0ú:ïØœbSw6ßV¨…vî¼Y·ÿ¬Ơñ;E–9̃눽Óј)“Ö4ªî¬¤y‘%r­íư£/¶*°²Kë’iÔ½§ ¢]l‡·M£¿æàdÜ!ü&f±í8n·åatv1(û3>û{¦KL?Đ ›p•-uXÊ´ö9•„…ßÉ]1D F S6Đ¥RTŒJy L"çëiÊ~Fuư“fÊ`¡/ÂjeLLMCÀ ´Qîrs®;³”Ô™‘¡ƒÜ ätmÚÍưhO+Y§PS»’úÓî`Kq"TºbHó¥C‰Ớä!Ç”ja3m’‹,É#y@åæÓ‚j; 1ĐY±ÚÓdæîS¥¬ÍµœŲʛËm¯F†(n/½Y¿[OÇ]”4¶'̣̉À‘₫ươÇÓÆ½ùâ'«­̀Ï<‹J­“?vz?øDÚZ_ûă1ƯIG°ï™:ÇÏ|¦ˆâ­Q¡ ‚¦‘ï̉^—Ñ-Œ¶« g¥Ajj³“Ădé«:Ùè®Ưæj«"̃đ!́‰5’læQ˜}”íOilSèÖẳt{’÷ñ¹œÛ[·tèá Âœ–Üü'û„™²ÆæùSÉ÷®tSÉ÷üÎsơ¼ÈÀiD[Åem½B%}û¸h½ºâ¸è+ÊFWEM›h^:ƯsàăÂơŸ–³ˆzưDŽ„Y‰S\e|¶ ,ưÉÜú ®×÷–Fz‹œµ³3îÖÜü¹5[ÁŸ!¯ i¸WđĐÛmu/ËôK¨”;›];n©aëÜ×5î½ơºưe‚L9rÜ̃²á7.6u7Ç 9­ùY•ƯY½óÈkmö2–Çtö–¡³ ËYTB4fËÎŒèÜSWWW›»ÛƠ4øÇÆ‚ïƠ”-Êøæ GCÇ?@OOŸ¸ß†V?K5\ÏÅ·_.£v?¾VüŒÙ$Ơ£]m\ßîjJ‘*¥±Mmøèg¡›vB—¿̀½©<ÂP·£Uk˜Ä»QÚºíÜç‡Ü|´—!&×Gè{LSñ®GÂẠ̈å¢n ¼yC£'MƠ»éË+…ç~wxV«pÎT0Q–²µ²æ ¹PK¾M'J•ü/¦<í«.í[£Ççœôµ™>çøÎñJöă§°¹̣[ /¥ ¨‚1ƒ|ky ‡“O7Hƒ¹›1ëKqŒ²ĂóåL‚O÷6†‘[.—ùjTŒ”1H :}WûlEù~F³;/~ï)áU®ƯílªB̃Ú)¦ï9Åơ7tu›Iê1d}̃\ ƠƒgÊKŸAz8 :V(Œ‰W@2-ªµy´æÜ ï¿àÓª̣ÓGOjƠ¾°·hDEñW¶NX¶C%¨å•<é§Ä0&¦l:'W"©Î›<–‚Iñđ/¿îÉ<˜¢ÙXW#Ö®{ùlÙRƒÅ^$µ~¥E£? Ñ'¼ßÈÖr<›\€ä‡ZÙû •Ù#3Fy÷#"¿ñ'M· 9Ơd[ºúû”¢ OgO Ôµg œ1ơê¬ñ5í¶bB”‰Lhư'¯o\¿7™‘zíÁ]́·²ªÈ´wëạ̊GAF× )ˆæ‚ï—…P­è‰º:‚‘^Z §Á”[uG̃Ë['ÁÚóæ¹º“‹ ù‰Ëul¾I›3ÈÜ¢̣¾I™I`±"C¡t;åzl©u¢Á²¦Œ|>›IQ @èÆkí̃©©ÍÚËđÙq‹¸«—)buoâB¾]=̣R‰ÊM%:æ ¹́‘”ºœ.mÙ°gôV‚đ«vđË“ˆ•ÄpÁ¥N, äÆN'×5Ơ6¤å»Đi3I„Ʀú#>rQe7ëâO•úr¡®æß]‹ ËÛp‡,ª¹Ă_í±”ĐæRĐtƯ3-}ơAo^Réà2ú@¢Œ–#ͺĂÄx˜1æ¶Hw ‘âW•¨=Đ[#$Îrˆ— èµ9wkz*Íp£ï2¯åCM±£7Ă#KÜ(BˌӫÛ>Hwê“/YlYª=O%Ôä‘ô£=.R+GÚ9N©JqOăGzg öNd”l ơËSAß:ø”n€0á^ˆ<×K}ä[?óíô ¡W̃“ÜÎäx³ô ,HPÆP¸§ø³.’'?ÓÙ?°5QS•rÇy Ï&®Ä₫ ăúå—–­J»-Ñ{ăçĂ}üø”;hæ®ëÑÜÚ­‚«r}…"NƯdͰÅ/dè’úoÂđ¨©ûŒMÂö«ăƯGºfj4ƒ@±Ÿ#ü®ŸEÍ¥ä3‚Ê_(ÇÎ{N@èè†ÊŸÍ.Q%Ứ¥uë'{IÓ$ùưÖ4“:qÎù¸ –7i0¼3H1 W¥«Ô;œÁD)÷q^ø ªQ¾»Åy÷Ô´©V×¢g†wKo4Y‰ÑG⸠,; [ƯL$ÇÑ¢ç~]s6([¶¶à£÷ù) ¯å8×[2X‹đé¶‹UƱi/‚bdžØm?ṣ¸’Ö:ªöñȸ³Ë^ :B>帪£v§”‡¶CWă®ë;Ü~ps¸Ô=%3 q©LSœN9CûROاæ©Û-¢Ê…Aă÷/ °+ëœ'7̉úfú\ÿÔ^©ָ˜CÀEö=bM5Un8*°Aæ>E/©÷ÎóÛsƠ&Ö»iB›ư0(n»úSF—ÇK•„~qhoß)i/ĂdZ/+?»[¯LØS+ÛóotêGÙ̀À«}?q‹û­[¼R¦́PÑfƠ'bèŒv̀áqRđ±q,1Ëê²̃ ~¸/¢öí «-…"ÈûÅơ₫ưï‰jæÑk̃¤$₫ß?›4.~Î~¼eç4çu¿ßhÊ>TäÅ¼ë”Ø#Å<½‘ I²~ær1krß“«7üÖ{6™.'₫ư—B·†L?$ ăàŸ’½D9œË7±ù€@¡<úư~:± C₫|›×ÚÖ}œ®aÜuö̀à3n¯½Á@6¹yĐ`ƯcºîÖç¶S/Óèy§²^ë'6ƠèO¥4*몣đ}»¹M|;ư—øÄGÉi,y¥ởø²%/‡ưC<Ç₫àÔ_¦©6SÓoê¾ê‚Ρ­XwÏ2W]̉× „ ]P®7Ï@é™đîÁX´ñÙz'Kè.聆»Qÿùấ› vzÑz/’LUhØ9Ïl ªÔꈛ‘øVmSé×̀Oö1†¯OjŒá7ó]zOI Œ₫D̃ 8”‹!+9…¨µưïëƯ*ˆ‹Ø¸X=£UƯ"X…‰NPÉể!©yo †jAúÍ>IO0Î7Ê ˆÄ|x›ÊNÑah̃ü,\ỵ̈ëx̣]>}ÿÍBÆcHZ¥%×Å̉Ầ̀(uâΖ́¶ÄÍ4Kú¬ºÓó·[bˆAÍ%µ¸tá\ù‹wqYËd6`”Pđ•̣T .9náR#R] èe±—"~b̀Àơ-÷ñ—PàgÏöO•Z¥¬!É¡'¸zU÷;ämïrïånÚ—´Œ̃~Ă-­=ñÀÇ2jB‘ȶ0o÷“ôT#“©æ<®éñǸ¨äă+–€Œ^Ú¹ +7+42íS̉â–Ä`eûRr¾a^ÿëöY{˜ÜB®•~Q)볈¸T‡fµ©„„ƒ½2óFàµ3«–¡7±7ăư§x˜á[œïÄ»Ö^6«µx‰Ăœè^ñ›tÅV¼Ù+=Çi|́‰X¢XƠÙIƠÏêÔKJS¨WơßĐđä(wà l>ë¬ç#ôY@ĂÔÚñH‰¦br¹*§¯*ă&ÅïÜ=̃ÍÜx/XÜ)}_AÚ?öt¯<$è#¹É )ª̉ ß³…F{ê0₫º~‹ôUÛ 'w³uééá°ø =×múº› —ªQÄƠ©Ïé¥Ô ÚO5ÛoÏ(›qÖ_ÆÍúÑđđ[– K‚ࢲ©óB©ÇR%)É£¬yH Z_ơƒut!À«[ÎJ~•}ëá·Hvo§×¦8}”Ươo™ưüđèåµLyƠvÆçˆ‘€¼pcu ˜êqê¦é¶¬îM1'–ŒÿpO:ốđO/U—Ô»Iç]|<ÁRÚÆ,ƒ&„¾wcÏM™k({>ª)¹Y{-Nr&$œtÓ+“ª!!w­RXÁ‚à₫î>–ª‰+8¿U|<Ï“[çÓ… w_båCÛÆMå.´Ü-yxäơ^¬]<2èÎƠƒ‹?!=dlTJÊ)y=©SGy9zKê…ï,ùŒƯ³…².̀̉‘‹$ ̃P¡Ø›oé…†/½«|›Ô$WÊ_62ÄĂà#ù% ‡ÏÁ Y =-Û’Ês Ñwob”4"‰¢¼Ç[ª́‹Z÷@JªåÁ+é¹ô½Ùb’U=úkêeïe¨ç§?EÉÔÉ Ëé {”Twµ©özXR•ü„hî;ưԫعáƯC’'*~jXÇÙXú-_ŸNN{á’3hé[v’â¸G‡O´ÍMʶĂT+¢|‘ÊÄÇm–ϯÆẵ¨oX’Y0euƠq°ơÿx4*]G²y:8~:·©¿‚û̃#./¨.LÑj[@pa•yÎgƯ»Ó±³¹2 FJZ— ²ÑÖ£Ö?:Kû†©bđeWÈ’놵¨^*ùaXb”ë̃£P4 |Kơ½ ï¸ÿƠˆ endstream endobj 803 0 obj << /Length1 1306 /Length2 1243 /Length3 0 /Length 2081 /Filter /FlateDecode >> stream xÚS TSga,LuÄZ”¢­”Å• KDĂvÄ"*SÉ y$y/ËKBŒ  rTÄePäô¸ EA, ‚ ¨Œ"*¥(XAD‹ è([E˜Â¼\p朙“s^₫ÿ̃ï»ÿ]¾kóMh˜#G€ÅÂ\ Åéó ¦ÓƤĐh ’M8‚Kà÷v’ÍX¡D0Ôí„—†pÂæ áz †‚•Đ™€î́F_æF£æúˆ)Ü€7¤F ˜0V’l¼0™Vĉp7đá́øö€î꺌l V |Á.‚¥Ä‹|HÂ0>ăÚ)!́Ø"—¹Q©†I•LçaO¬„jXô%ƒH O–F!Ù€p¢œp„aB\)`@$F•E… ` ^a₫A`• F'ÀA2˜l SèÂM²ơÔ@†ø|L*ƒP-‚Æ!"Á*nOÀÉBz $QbRCˆ%†Ô!Àå¬Qád}J¾‘áJ‘èk¤êĂmöA^˜T £¸’¤ÏÏQÀ|¢ïZêäpÅ(¦AuïoBơeT2jÈU°¿÷$†0‘>Úâ`°hLº« Àr'đETưáZlp̉ơf¢†D “!Qœˆaâ¤SBjà œ¨ûÔ1ơF¢Óáă CP̉Çè„N܉ù+°FÈhú߇S4¡0†J´á†S9₫^œÈÈ¥“%pzzb @çÈbG'¡S¦¸‡Ä©qB!d2O¸₫¨Ë&̉%úô>eơ¤́&ÄL‚Ê…ƯG¡o ±h|âCÿ¿ån ü7•ë£üO¡W%‘üv€ÿđCRD¢@ø¨$°âs@$<±°Á°QI?÷úă±4Ṇ¡}ˆ’‹$À‚Pç‹&db°Ă„ú§r}P>&Đ¯ ƒå …̉’h„ÄÀttbŸp‚A†€JA1œ ™ OBLẢÄ•¨ëô&̉”°|•BAl‡arÄ›ïï†U„á˜Ojùă»§Æ—¤V ÿı̉8>«g8™×ôï4́ô™¯~¾:Å‹ưn€y<½™sµ©+ưƯoszùăeâµóhâ¿=Ù”î6¯å\ÅtalySĂœå#½Ê £+đÊ•u1LT7ïu9¯V3¸²Ñ₫+²¼ïÙưÜn_öwåEoψ^›Ø^xI13ªÏH7±tqa¥Vrr+‹<‹9MU₫K”ư+ë_eZs»ße߸Ă`=­yx< i϶êé1—æöxzQí¼ 0¦4ÚtVûXîµK¬HM¶‹UÖ…-÷ư§¼ôÊ‹´¨î4&Ë;b[̣Æ,SN E˜Ÿ Y²|S̃(¶uj6i]»9>óôƒ{sëÎƠop2;ơÈ7&Kư`÷f /,•"~àE/‹Í>\xX”¿¯”;₫EyôÆRÓlJ:Ë4´˜ÂeûÔ-`´Äïlo¸5,´̃ÀơÍ>î‹¶GJᓱäÆÎÈÆ´ ×¬ÖüïŒIƠb¿–-ç´;ª*Oµ_ºÙrưVæÂb[nƯ¼TÜ₫ï]«’ü>ù=2ÆÇæ_̃ÿƒ¤)«Hv<á\ỵ̈˜¼–t¬y<…kÉË*h„w]¬]p$ûBk´°»Üô<%iƯ¢¡´gC›~ ¿íµ¥¦-ïÍBVG™§íѸQF׺âEƠϸ6ºå.Çzv²ræVăŸLÙ́¬’a¿]¹ê# /ïfÊEØ V¥(k,º­ä‡óª{æË™¡¹Æî#Cg/ö?yùz|LÑλm1æ‰ư<îƠ₫óñ«˜¬Û9gùÏͨi]ăĂs€ŒwÍ¢zÛmö½m¯ª:~Zc₫(Ă˜·Ó×2cˆƯƠ3Ë\°×ïÀ@ÑÓ®¯/UñcIx‘í¹ËÜ)™Æ©½¼›'_´JiFíuíư§ E3®~›³ĂoZß=†ÏôÅoy3«êûtSøË_B3×ñÓö.à;”Zï¨èÓLs*ú>Ô1éÁ¦WZ²çµ6qfgùz#̃ ‹ưNâæ8»öÏƯ•œd­i“vçy§DÙ3“8øC‡pᆨù‡ ˜Ñ+ê¤å/;ƯK”º¤®”íWÊÇ[̃äXPF÷-ι^'¦&Üóiÿ2`́_¿>Œ¨aDöe–́½P870¢·|Ú~ÏCE«¾¼₫¬öKqø/¤"+—c[“eÈ“ŸuR¤ ËA³4Í¹ßÆ₫ÍáÖŸ[ ·h[O¢Çî•ß<8¤®ïá=£Ü–Œ%:¸í[yîÑ3.iŒmÏḉ¸íĐZöF…5Ù•†—úvK6†hä}=‡³è‹¾½¶üƸ¶¯íx~Đ6iúÜwI®®(åºVY(Kf±'í ơÈPi‹ .M¯ÆYƒăw¾Ûµ#:Ú̀v¦ØÈ!/¾&B¸¹§¿®\Ü×y½fne’{ÂöÆ”Á¦”ŸƯ•G½ç§¶¾ÈV¯¼X'+.®mƯxû̀«· ç‡ó ²V¤Tôûä^\Ư]z–}®­uM̃íe!9…W%¡Ö—†}aưWdóËY{]̃^:vè«Xläî°Ï,]j^oˆelu¥]!Iû£l…o†•IûÍ=ó£Oo´æ˜­Í_oƯƠë·ÅÏi9eºơXW$°aº‚¼₫G¤ô=d_̣È*ÎĂÇUû8ü~|óÀơ;¥´}‹œBTŒ’µAÂQ“ŒḷÖăÿ’Ñ%å endstream endobj 805 0 obj << /Length1 1144 /Length2 4296 /Length3 0 /Length 5052 /Filter /FlateDecode >> stream xÚuTw<\[»&D ƒ`ôef´(Ct‰^Ñ 3efLÑ{t=¤(‰DtÑBD AÑktB!zw'9÷œs¿s¾ûÛ́µç]Ï[Ö³7?·¡‰˜ mĐD£đb`q2@ué„ 74æW&¢„…À‹†ÿ5t„iÀ‘ø_í…œñxŒ¼„Ɔ bâ8Gq/!L,TWC»ÿÀÑü™:‹p 6å#ñϹ¹¢Đ^(¿ÁHüwKpFâ6 éA@ÜTÿß`"Dó7æ„À¥ADx̃οRú`¿Iđ/†‚øaĐ #̀ ‡@:"ˆ/?̀Äc ˆ¿ÿKüç ‘x =‰x «a„ă{=‹ôZ‚ÄA 0ôëùkeM¼P8åæów¸>̀”0S¿enbv퟽ÿ¥ª&Je¥€bë̉D§å¤%ÿ©hC₫oE ¿ßD9¢rNœØŸÅ{"°8¢ B¿ + üO%}4é€ ưm+4ˆèâ ü_ÍóüµĐ?shÜÜ~÷/ôGă@bç8 .đWïn0́¿ÂaîH7ŸÿràŸfˆ?|₫ÿèÜÄĂÜ*('·¿Æ„Äi"½pC$̃ÁùcüßFÁqC4ù뛥ÁÿàL‘®(Gtßo ‚ÿ#¥Ê G¢œ€&x¢ÿ`Xø_À/Ú€ÅÇóû‚ˆgÿÜ;"‰"̃±a´ƒB˜KyXƯ₫kv/±¯Ÿ%[dn︤hâÜHçÅÏ5ë\óÙ¥í\OÍP7́tV*±$Ó##H`׈“ơr•S­§dd g<§Íö]¼BQ_nƒJ¨÷'¨…-ñ> -kYͧM{»pל_I­›Ñ$Íıo±ôÍĂ€‚³0§˜ÚàÛ°°Ü•ĂĐÚnF̣ƒ ê —ĐÈ4Ú[oúoYĐ¾ù¾ÇT\Ïh74üA•^:h0B‹_¾aÏn/+ßĐƯ9t®×¹Ñ@Ú$ú2&[piK¢‹öt¦CdœÈ1Iwè ‘ÖuWs b<ôüC}ŸPƯơQ1”Ưª}©Ò”o~f6/€ K©53÷e¿¦ ̉9R?vÜr²¾Ö~¹®æĂÁă;Ăî,“ưÖ‹jÍ :³ó]$eVœ$FWƒĐ¥É¡Pô›ÿ›&¶ïsÉhÅ×J¹È©¼P\¯´cB5”$d$Qq­dr,ơ˜¬ÛlÚœ5,Üưà7Â6\,#‡Ö}Q7%ốL[kD5\Y¤‹ŒoRẳ‹åôyëfß•I/™¬×_ )ß o¦AíZ^å#´ä üX³Â(Zvç… À¯ñ u_¢R…rƠ»q Á£ă^}ÉÖÖZ‹Ư?6™ª 2}54é ξEF÷\PŸäEi2@jé´D©9HÆ­Đ,…?>êí½`vèHtl»rÙcfOÆ×’v·¶}ó́Ó¡ú]údwË’N¦{îJ‘ÑIº&!¨¯Dœv©ÊßSr8ȸ) ́t;m+ú)&{†?ºœø–Å.Ø z!fd•ñ£DÉ… (},lB.–Fª°¹dGWæơø7½¦£É%]R饋VÚ^‚t«TÍåUdK‡™DkyV7Y†/ƒ«uÖ(_§£´Ḥ¯€¤3˜+̃–M‘ùøVzùÊưHr1Zw{[ ]ÏŒ¬J[ ûvª?ñZºÎ‡û@8E®æü Å´«HŒưÖÖn]ß‚pÑH _| f½on1¾É́|´_=´9˜Ù°Q×ƠkùªÁü^˜y­Me×e^Ûă=wM}W‹Ç n¸^uOưi”Ÿtï₫é`©„‚ăk I63½ÙïÛâ—ơCl»åHJ¦?gä%yt~3”jH§3l¾IºL³OÈ;9&y@ëÓ‘ö¶vƯ~Ü€²g‹s…$ƒÅq“`YK99é₫w¸+D¨L²nŸg~Ü\~¬¥X טPÅóăí+kÿOå$_ŸÙM&âƯæ´]º'3j“Ô À#ÅÜFv¯æ–“'‰‘¶bW<ü;)2{7^)â¿“RØOñ®„^Ë}é»0Áû¦€£™c ? À4bÁ‹_„Z5ßÑ©9ïÄ0;ÁÎQI}ä”sÔÎ uÄ+ÖægÇ•ø Cêd‰:VÜz½Üâ_/íŸÇÉ6âïö/øY~U#V2¬`gqIäXwøÉÔ‹$̃nvñ 븬®Å!}m\#oPÛL’ˆbaÅ1ư“~Ȫ²®ê¨ƯN£ÖÎ9=#¡n?ꘅS¡óÛYc áÏ ˜µº²Ưu¼¾ºµ®ø r“4â4¾^Sv\ ¯ è—ÑmKÛ˜“í̃|äö£!‹³–^uß›B‹2wÿKâÚ¹ 3Ư³ÊvÊ®u”_ˆ¿¶ÔôXIÀXN¹ï*qªĐu†ç¢ú´®éêé4TYô•>Á‘›Ơd—Ơç}B¼́HÅ™ÀËă¯µndjÅZ<ƒ3ƒ¤9đ7¬×å²9ŸRUu‘ e†₫–6,YúåC¥ ­Êd…FG“ –ïéçºPĂùrï'o5f§R¿¿^åŸHzQc±nÉÔ˜}:̀ijE:¶§œó È¨§!ơp)J¶0¥’˜t¶̀Ó̃{9£l£3q)âw¤d`dÛfD^*¸^` ö¸ p¾s¼\1èÜäMAêá¢i¯ísmŸ·ù bÅq[CÁS{æøhÄ̀ 9;†¡Æ›ó ™ƒ“üö:iÙÏoY·cnGe“S™Ëè mYi%iÔºmAî” $»ûB®û'ƠV†i)Ê=lóM̀¢¸×̣Oå<Û̀Mmü;€ &½ÈñkîUâ×Ô)̀ß7äL ±i’(K¢³Ú‹ÓăÙùV®ÓáüÁ_«N\ô&Ïh¥w¯nwNgˆ:­°Ê—¡mZ½3Á‚ă‰ª9ƯQÊ”‚±Nu‡a܃r ¡¸'‰ j(^z .ó´#fw{Pf†îÉ4fD!V1 81(Úív—6á—Å«üÛ­´ö—b‰~Ç78ă(9Đ L×+ˆ¤›ùqs.;ÊĐ]¥Àö›È#®ét°.gñYz?̃Sœh/|),Ä·ƯÈ Ơt¯ûàÆ­0¢Û·r.æMkư½̀½áç-{  KÛ Æ–V#¯V•?Ñi<ÔÑ{Ó‰óͦ4â<ªïê—¿%qö¬xƯY†Èæ̀âYo¥Â¥^àđxó¨åv·ÛX:«Á«óC› 6)…–íóđ)3;V5 ḳVf3!oæƯ#ƯjçÎ`®^iøj}ÿk%k*9ï#7Ô³ôÔ8Ïo¨T%¢|áà)Á4“nó}ơĂô HV Ù«‰ê³"ƯÏ/@è·9g¡¦7 zs­ëÓ?_:Rr½”·IjQ ú®Ëû±Äxă’‚ ₫½‘*¤E[x̀†„6«ö!wÁaÀQxèớ¡··²•đܤ̀+ºuïï ˜RCó å9Ú_m øWäN†[R“φx¿a!’la1ÜK’–d÷ÚîƯé¶Für,)?2èK|L-bckơˆL.@¿°•Po0ÿ£üÁlA€%A’Œ-gBDçJ`crûø-t›œÜÛïÍ,Ÿ.D¨Ä@ ª¦^ÈÁ„̀l\äL/¿>tKmz NåJ>ơyU¿Ùạ̀¾@ÊÀmgÁ‚÷ß#Ÿ}Ü™éZM®ˆÙg̃Üa-ß Öhÿ9«iTù0;ûÁb5äLd^ơ ¦æœ̃-£&Ûf¶³ÏÆư+ytw̉›<-Rî 8¦·îmá/ ¾9ơbËTĂ€M­f0bOc³2kµ©đIs₫ë%1[Çü¢ͪU¨µ8'î_‚-½ŒMkn›!é$ˆMCd?®”óă8˜ëÜ;«Ù§2[ û—K[ß{ÑÎ:1_ŸÈÊÚå5̣btH)B¥¥Ÿ*Éơeđ?†M×@ĐyùdåY°7›.ÍÆỴ̈Mßë{/ø|FgĂ! F*‹ê«HˆPÖI,–`5™?â¼FÅ’/?|6XxÊ?qû{î´3[q¨st(́±Ớäù‡Á–F*¶Âgyr¸YÜ~đ0ëçÔªQéô(4ŒC±{eVQ~à‘"i‰fû)ÿjµ­Đ’8KñNà`.Y[æ#ÖÚsf"ö©Wz Tô§ôsÇv!œ‘frƠߢ4\Ca"à«<̉–ẪI8z}$X́wđđZ•‹̉U –yøé%gÛ7©×]¸]Ÿ® Œ§}JÚZ»úFO}+.Ä3–̉_ 1Ñ´;¸sĐªâ[z‹k´0’;Û]_#Ó¾Ó=9¶ă)û:¼ä`I+Ú+VÚªÛ lÙ>çw¿Ư¸ưUQf•₫|zqµøÍ7¼^ËG— ùÇ?îøH¾èA™*&>>¯º¢‡‚̣v)+¥™̣‘$Ă2(h1—m*OÖÖöm_¿0•¹héCrô#̉)îPfÉṽ‰×S -{‘‡¸ëCưêâ¡‹Y »+ơQKØÚ'GĂÈNeƯbÓŒñB^ỎsỠl ZMëÑE˜c˜Åø0V°Ÿ²h&ZôÎ{i2ˆ´`×Êo!¶Ï5i‡SYàèƯ`d¸@đ¥aå©Ûëx¿4•₫“!Ÿ|3o@˜KÀî~P93ØF…Óו€–S¼Ü¦L ?-Ø-SËÇüÀ‹FÜæ¥JśÓ”M„u–-]@U=,Ăz;Fp$KڏÚܰ?“®Ç—pXº̉ưà¹ÙƠ endstream endobj 807 0 obj << /Length1 1626 /Length2 14808 /Length3 0 /Length 15655 /Filter /FlateDecode >> stream xÚ­·ctåßÖ&ÛvvX±U±QI*¶±cÛfŶí¤bÛ¶S±uó?§»ßçöử÷ư°ÇØkâ™ÏœÏ\kŒ‰‚2½‘­±¸­ ™‰ gnmàä¨dk-gË-C/kldø²³ĂQPˆ8ëÍmmDơÆ<uc#€¨±!€…À̀ÍÍ G±µss075¨T•Ô©iié₫Ẹ̈OÀÀíz¾2ÍMm”_œ­lí¬m€_ÿ×‰ÊÆÆ ™1ÀÄÜÊ "¯đSRN@%!§ 0¶1vĐ·(8X™d̀ m©&¶«†¶6Fæÿ´æÈđ…%äĐ8Ú¥»Ûưă¢Ø;X›;:~ư˜;Lôm€_3Ú̀m ­œŒ₫!đe7±ư!;Û¯ë/ߘ‚­#ĐÑĐÁÜøªª *₫o@3}à?µÍ¿Ü[“¯H#[C§Zú—ï æË Ô7·q]ÿÔ20™;ÚYé»}Ơ₫³s0ÿ 'GsÓÿb@p06Ơw0²2vtü‚ùÂ₫g:ÿƠ'àë^ßÎÎÊí_Ù¶ÿú_̀ÆV& p̀,_5 _µMÍmàÿÙI[3Ó¿íFNvÿÓçĺđ¯Qư³3Ô_$ôlm¬ÜFÆ&pŒr¶À¯’ªÿ;•₫ûD₫oø¿Eàÿyÿÿ‰ûŸưo—øÿï}₫Ohq'++9}ë¯ø÷øzdôm_ï @đÏCădưÿJÑ·6·rûÿJúÏhuă³¶µ2úOŸ$Pÿk$B6¦_²010ưÛhî(nîjl¤`44˜è[}Íë_vU#c+să/]ÿ5R=3ÓøT̀̀ -m₫€ưß.c£ÿ¤ÿ%Ơ¿È3JKÉɉĐ₫×*|-PÅÍî‹ÛÿhEÖÖè₫¶uxĐ3spèYÙ˜¿î̃!n&¯ÿCÉ1ÿ×YVè`î Đúꛉù_Ưÿß~ưŒ˜¡­Ñ?k£ Ô·1úÚ´ÿeøÇmèäàđ%đ¿.ÿW×ÿóü¯76v56„[Y´5ä ´HMÿ ¬ÁÎƠêía ²+®W)Èó­²íöI Ưæ.×{«bh˜äùhu[8µ{ß—¢9îÁ²úÖlü7—À‹ŒúOêe;'í?£N1âï3ơHËy™-M&µƒqE%¢7(ÂÉvV˜ËGj_2ç<_ ̣;$oĂ”º̀”´üÓ3Ê„ăLJoư#CƒƯ×öñi³b`)xơ±½“NInzwơ†/Μv ª#NvR+" qFmi²&•4>éŒ}´• ; ƠU·Ö²Ij₫¿"…­Dªgk%́!ûûAêcÓHJ!_Tc{£!#‡pÓœĹŒ5R¬5-Ta¦=èa' ôÄ%̉®l±#î|,́IS~µ̃́roüiÆwN@y„ƒ¹/ ~¦¹/_ù #@­j”}‡¹&kh_r™øæ’Å#“Ă½êNuµ9l0” ƒ%xÇO=¢]¹mÀƒ=\ø@ÿ¶™ÍC_5}¼jë‡=i¾ºˆñû`3Yăδ‚~ă“ÿs)—á”`¾pF†ö‚øCYĸœÅ_÷éUŒ°̀QÑnŒ†Ût Åƒ– c/Ư 5ÍƯø»o+ tÇœ2(%5ç"%ơ„há¦D đU–M̃|-)çhMÅßÍω/½“`@>ˆ_l?=»Ù ïC˜~~hÉĐÁ+ØâÉá#Hq×Paæë„̃éÓ¦rÁ@ 13)†G+8«$èa₫ƒUçVg#6Ơjúsæ×·æ₫̃X‹¹q#Q<̃(†r5I]=íY{Ơ¤{¨—‡?k \yĐÀØLÇÓvØ^›îq₫•y›ă×­_Ñwq±Ơ[&œđ¾cÛ匢ué'×f4Aº&ƯĂŒv)£ÖiEwơ÷×Yè•ñGÛ(m_Ù +=ñçIVơ  êQ\h]¸Ơsz±§1Û\‘ă²–û‚ôc©ơ“/JX]â-đùhjWñÈ[º…•WO³́}ºHîE¸ƯtY@”a|·aS@mm62ü₫( ̉b}×z©_LxÿÜëÅéÖÁÚ*0̣£×»ü₫K-… ü3Å (5Y|` _Êß½́{å Ùq‚vRb°B °_ÛØ^í*1 ̉)ËCfjÚD‹I÷Ǭ¾5äđ)ËÑw—¥w㻬¼Ư…áƒ!Îï̀Uø'ª¥£´RưÓÏø}T§å%̉đ7oÄŒˆRa£¶ÚÈÙQ˜v…~"­ÜbŒKШÜU,̀‡à1·]>-7‹ßlÜ™¿(ísø¨0|ç4̀¯{đsn4̀&»eKËu?ÓVPHbåA½»µÖ¬”ƠtƠ Cß&£…^K#é”Pê'CK—E8P†~̃¤ôÀ̉·ă8¼v™.¿*Ét«‘²çÉç·i~ï°ƒßWÿ ANÎjj yÂ!T¹¾µđ—{xăË[Tt”Đ+Asnœ ‹¨]=·Â¥ÄçF¨!ØÎ_iX™À¨º–Ê*PÑjæ GÁ+ª²̃–/€O–MâË”̀ vûé>?›oNŒ̀W“Ë"¬|ôµ åjVØ‚Ñ̃è®%ÔăO\ïùsKŒ0PMï,Ù¤]—rƒƒuïq*f v¡ÏH‚ƒ°N~KƸQf@ÎÙ'­½|epNÖ4$±O/@5¨í¶Ø´9o»>¤ü>+ Ó¤Ö„:Y^àa°r†ö†§RgZ§ËĐ5Ñ;Q £í/}Ebjè ©Sæy6’LF&ùtmj–”dĐ´ƒ‹ÜoF7gBt<̀2Eê—YÑÇ>Hã́ĂP°₫7N¶=#6LŸUk䵺âñÑq¿Ps´wÈ YơŒP̃«“»–×đ0m2É h¥Ø!p ?´…®+º§Dr:Ʊ•́Åé—†đ…3LO˜¦"i8sÍ5äX[¿ÎË Àß¹đ*sR†Ô·/.¨Q­m[ƒ<$%ëwÖI¼Ă‰;Óư#¢m¢:G¢È.ä‚v GƠŒÔ‡ÿ.Ä₫´»ZÏyíàd UI-½K*>aÙÜ¥]ÓI²EGSä'#^ÿ‚0훳ë£Ó!q ñ›¦k|*4«¼ºû˜đ!¡}rê[)JóUÏ.ï꣔:Ă‹^NÓÅN5EfßécA´C­̣åK'¡#Oøú;Q!å0tĐ$«nô@¾LO“9) i×gú†ºOêBk(Ư± £Ơ·¸OƯ²H…)l#X¤!SƯ¸¯__›ú^¨i¤v'î‚?ÚƠ< ²9%d(¼Äc̉´AÓÑđQºí­•K·»ÖéÍe>cz¥E”̣:₫-|-Çp€ÁezXBçÛi\`Äe°k­øê¹áAöŒïẻ fm$ZlwÎ"̀ư»ÑOGÓ~¤&?̃Ï-”Ê+‚]v‰%Ù‚oÆkúËk÷+B‘ĐóưîĂ ªÉ²G`k‚d 0¤Ieh͵rcûŸÔe¥#uåc%‚uû¥Á*ñ…ꕱv­¦XI³bÏ/H ¿©/tß †á³¼³[44ÂfÍÍ,à÷«J6_h́G/ÂúA¾-§A¶Ñ^€€ØÏKôवơ/„¯ö?ÊHß ¸jÚ•_̃HH+`(ál„f›₫äÚ ̉BShf̀¿ưsÿëï¨xö•Ÿ^Y˜vƒÈ£'y'°r–;q‡Ư]ÔËv[Rfë¸p–=eNßÆË¯>®+`ï$e÷âƒl’³Ă‰[ŸEyuU,|ï3­¬¦DåG¡iÁºóR̀O›oëÈÙ¸T²Ï[/l3²ådĂ‹SWSBºÄ0ă&„á Ày¹…A1µDö¹'œc%ưY»ôOÙ‹×’¶tªÚG̃–7—áwÄXÜùY7Çd!´XB̉9,ÿÂ₫â₫½"D—Ó3?ÓF7:´Ëë ÓbCrĐÓ7“?a®F‡I·Æ V0ÇN3uyÅ‚§́”(!%ëb£ …ÚÏ4H³a•?‘T¬á”âûÛ6OY%ÿzÎaÍăÜ̉“Cû̀‚˜¯Kqe?™́*8·d^´*n~#øweÁ7p³g¥Ăß&F—AËäÄl¨Å ÖÈä †=Oür£nT͉hË•$(½6n¡OA±üeHáïƯè@zÏïÜùƯu«øûùä+3.Ïoèlº™ăY-̣Œ*Du/‡>+÷NăÚû0c¦¤/Ăó?‰ª†‚Y‚²¼¾ÑuÓoRè|<Đn$ɇ*t­ ˜g—¸gb L1…xôa¨jÏ×4Æ ¸Í@fÖÊ»EJ'×ëhxa;vï˵lH[@/ăç˜X5¸¼iy¬‡x–«ëL#ùÙĐ;rQNp¢Æ̉‚Ô®$D^~‘_ ú0Épư¸ ³@‹/áêó›.>©…#’M¬¾o(ªV5#É´ ₫´^Që8ë’­ ²6oBPO'jé+6hFÚÆ[qä>Ă!:&I^`~>Q/X¢R;øKÄf)UCCnͧ- ^ÈàƠC¾ñÛ Ơ;ϯ’À̃D’¥:물Áfë¼âr—h‰M%—#C/Ó¹nt2ü°)8q¤…~µÁÖ1·K'ù¬P}́¯*µÜà{-™¦5ë¾ơhÊY¸tAËr[ >.V,ơ|!x„ ̃–lñ×YÆaĐ2!qđ$$Ç'†Ơ\^'±F˜¡áu±Ă{üb»œ3˜«̀}Ó†;XX k2ÙÉZRYI±à­|ù2r°‘!¨}Ÿk‡¦M¤XSE'ˆ“ï0W(Øw [mß© n\Û_"đä®ặùơ5Í3²A¸AÄ9‘iCŸˆ”p¡ßánÉ#&eá8R1 ¦?¶Œp‚ÖÇÍ^/‡@–µ¿~É–Pi3yÉwÈ>¥*´—üb+11?ø‘Åđ‘ïVÿd ̀XoM··×®ç&%ÏGœĂtÅ 3‰L×ah| ¥Àd @eîÇÎQVcg.ùÇ’O½Ÿ ̉ôÙ“´…ƒ‹½zSeg0OFm•7²ô]îñŸƠ°+”±¢y»ÄÚÖ›zÆo£Tª—-ư¨7LJ8°ï ©ó)¼Zq¸ÔA\ U(t;sÅuc@ ß…éăư¹ ]|OHÈ/đæ³½l¾uk?’|'$-Ô%×f¦-"ăKƒDcÓs7cÆ…LÊúI`?;E¬;²‘^|ÖưºXD 1Ï;߸gœLqE¸äïB^åăç3]Q=X%ê£Â₫"M¹^F{œ]û$ÍWĐ3“OßÊ/øIr̀₫¤±) |=Y€–Î₫A|vè@±̀¦bî@AÔi¾ªs)Ú¾ơ _Y¬_{¼̉{’j È;BËĐlÓTáç€U{Ë>Ÿÿ<ŒÙ‚kdÀBSø¨Zg₫»Q×Îk5úÔ§­(S"æ%0¼_‡¾0Ëâc]©̃¬M’y²†.¡½»-É-6Àîö»ơ{Ñ„_0cœ>;YeÜ‘üú„¹ŸbÏGÆZuƯs1¯V–Üï£̣úöơ%e˜$$óÑR«¿¤Çák/#É̃VFñ̀…bÎ’e>œc—³‚́n†¸èôñ ×Ä! ™8³RqS%Sf2@Ü%©@TGL4îm^̀₫È=5¯Ơ0ÖLÁù8-Z3i„7’Ï‘‚¶@•ÙF¬˜&ÚÛ¦¨‰ô}§åK¸ḯ¬ÍÂ7¶y‰Â-Ç7ñ“R;!Ñk=đŸÖ®0AG̉ §̉ưÍ– ŸraØ8Í7-̣(ừf­¶ *!±¶ÑO-_K»xûƘF¤₫UOùY%,g¶ÊîÚ Fû ¬„¦©Å%̀W_N|.N*ªøÉ)HR#.olbúׯŲÆo~ñY½ØE“nc¬:¥B¬K¡£­J® YÚUâmB*H§N&ÇWxе&9öX@„­øùTw\abM̉JÖÏÍ)oÖTéÚ|%<*Rë*¬ĂxúỬó±¼üáonÓvA±³0SxYUt7?z^Ú(³åÚhk¿˜¼6oËóX»¸MŸaáØ{°4ƒdßv£…£‹+.´Ư¨ Ä „†1pSRöUÁ,í;¶Ư`íÀX,Vœzª…’H™oË!yiL¦zñøèH÷Gt—íœÖ² ƠÎ`6&éÑ€Ë\l½i8ñ[^¾o-U–Næ/·@`Q ]1DxáàûÛå¨5QåS­Æ_¡đ=Qâ¸^_ >_=Xưµÿ₫Ñæd¼®DDÉ$Æ‚N ¥[¡Üù®)MU»SÚ"§ ÂWÑëư¹8U£B¬S:¸ 97èÂÁ̃\.·å¶qû²ÿ‘ Sî¾âeô䘻ˬçs§†“Ÿ©µ9́d+‡ÆÓWBø•Qµè•j¾4®Ø·F%r¥üçU€$¡Æ~°¯J°¥\¨&H¥üÉ ›<¯̃_%¯)î½8ÅvÙ"¦MFˆ°˜9¨ƠÅ ØÓQÛf>HÊmùfúÓ\¶Vc|v)ft3Œ‘†"́;âÅs›ƒ°ŸßgÎÖ¯ØïbmgĂÈTMeîóï!•üJf·wo¯rÓ(@D'ÖäD¼XØ„p­ ’Ês@…H`ÉÔÓäta·çåÇႸPóÆơÉÀºLjh%tZO\cƒSø-Ăq®TÍà[HÁNÈFƯ+±ËVÛKB¿¥.~ÈL¯—¾>ƒQ¤ÛÄæ,Ù€Ç:›»>´đUđãtŸ&j9u‰j÷ä#•6 G̣”UÓ̀ÈOKwBÚºæ ‚‚F„¶%¡›­Ÿnư!®Óăy8ßĂdËMWÊûu /ÅeĂR§¡/‹jè'KsLÆ€è_clŒ„%q7³đm; ,ñ.àlmkçVq«8™±àĐøñ*üë¿Z#?¯øaSRª̣ă2ñÀƒ%Âơÿ€QđÔ“r(kÈß½' S·á’;̣<₫%ểƠQ Ñ‘d7ÓsèăÄÔNoºÅ‰÷™§Ë‘̉é'KƠ5|gÔOÛR—C ¯ Ú[¶-où³ë$zá4™YÏq XH몬3ús°j̃P?~̉¶̀ iF#Đ®Å¡I¬$*ûÅæÏ½ñ¡lX&°săËw?×"ä"Ρ¤(½¼²óV.sôèuÁeÛTÙ·é"r'^§²±H5ă]ü)ú]Ÿ÷NK•4%@°0yA ́ÁØÖ©;Â9:w‡épư΢Ñ;&æO†4ưå•̀o\-¦›bp»&ë¡6̀ßsèă50ƒæ«-OEÅËÇÆpǼc¨L6$­f`„´ĂW‹A¼7ÍÛ„—?…FÅ­ˆï]că5q…›*i 0xlb¿óç.9¡3÷h=Ygü—™ï̃ó’{A‹„°ßª¢ỨhEÚ¡ÔHu¤Ûq#4‘4̃•X”€ö®¿ ơ{‡³N‘×^ÚGé֪͑ûî´CzÇki5™sô¥ǻ~âGÇA¯Lχ$÷‡$2¨´«œ‹ÜNE=©Ê5p;Ù¸“o¬¥À;w©\ÿÑ']e´ó‡éz_²$–xvưù°0‰P"Aá%9áIY­iê(—¼i|ËXe ḤYç,,Ÿs/TŸ₫ĂX™0í© rùf0eÓđ˜f\ ¯‹Ư?œsµí.ÅfÄẵlbjÁÖܾ7Er2‚2*/Mr¶–…{ĂĐj–ܦlçqœó‡™0»\z˜„ÈDLf€đn³±œFúDø“e‹<0~₫.«B'zt‡,¬Vw@SnÀXœ\à…ÉB̀­Ä€FÍ!+›Ô°xWô¥A¼è™găŸ 2é‡ê:ŒS%‰ª(M wRÎđ]æpå ˆÁ ö”¥"‹°æè¬áΧ b€ưWŸ×å9A`›„$]E¾ÜdVuåQê¯`°÷G­cU-E™Ûf"*±̣>×ĐÉ́Ç{üú¯I˜Ÿ#CüÆêl8Â×ăö‘#wßé¹,«a*uâ ÀSwˆ…¼Åå×kTNª³j\í|Ú€¥Ïǹ1ü½1:ƒÜudbs¿•ü}j],&î)eüÊ|óZ#uI‚§~{{Ú´#çŸϼÀ0^¥§ÏPçpæ‡2ÿ:üÛQá;ă¼EXÍcMzvdÚ1KÍjy'‘éÓ媖TPµ"ŸƯµokiȵaÑóĂ`cϦdåG­›.kp$ë,4êX jPc¢²óͱ,¬Ø±ă·/EmØ)³¢o²¬ ÓCÔ %¶OÉ,̃ ø¶XÊ(>U4­"Å Ơ S˜¼Ó/Z§c¶Àå^¢U g·hØœDÔéø k—a}€‡1kX¡6üe#SïÀ·§ .a7]qDÜí«¶QÄËTuKë{ƯôhG“3îư§Ùߺ×Êñ H´îµưk`aè) £€(™:ä>ƠÖ’àJI ey½É̉b™ …x®Nü¡e†´RùÖ Y4—ú»8œĂ ^” êÖóV J<4Ÿ]èVkÉ(©æÜ ¤ÈÁ“!× |«Æ³Œ^oy¨¶Ù™i?Ém–¥×h}̣Ñ7eRí¡!,c²bÑ–6ËVAOö2Aơ†¾̉ăE‰÷9’̃£¯[)äèßq J¹o´̀dÙ 0ÑÈw4oUPÑ™6Lơ¹h 5séL{́A¥³O×yNÓH h₫ änú=@æf.¯̉[á \¾…¨æB\Äu7ËƠè8„₫HC59ø¨ă”*› Æß¨Q«8ª-@äăĂ6%Âôˆ•Ä"±TKÖµuúÄ €ă,uơ?¨a~O«€Ư†-#¥…©!ïF?z̃ZÀưå°S|KŒœåó7Á6§ Xrl`±»8§º¿ç.…ÔU&·½N’,i~•à’WCÅ‹́Q-›R“§ø<ç.³j˜½O%&8¾k̃Xs¨Ăæ¥äü¾b¡Æ‹gqQë5qb%,4An ÁÏe·e1h7$JHd›¶́̉  Èx‚#•Ûbư¢Bc¹B¸Ư>R ÿHg₫¶rî_û÷|®Ầëz(ëºÏ¯ºdz†+Iưªh*o"ŃMĂhk“ưÚ~\+#‘éÁîLG§®WæºW\ϦÄǶ#D%£—¡ñdń⠗ʅ5J=à/†ç¼úO»:d§3Aâç|t“›A)îđ·ä›„bàƠªñp˜Û1>«’H%áùT‘Jđ‘¿*Ø3„eÍ00è"öƠơ¤¥fk+‹s½WøíböËÆ®Q:púƠ|ncI©b^‰•ûVư5ê³xÚ ‘‚up7Ñ(D…jrTG¨~X³&ó®.K›ÈØÇỌ́ĐËQ‹l®>;rM|ÙܘSW”#˜ROÏ,È ̣¹ØZôFá—ŸrŸ,ó ¦;U(®̣vƠjwgUó,ùåL^wăÏư™Ú́‰«U)räS»æ·©ĂÂjÑơ8P‡%û;ª® X §-zvª-gœĐÂI%'j"|M[“«¡̃„ Åoó ¯»Af×ñ¥₫ÍQ³í4{,ÄAÔ„Ÿ“øª+e8­‚„†9ꬫ¨[=Ôg:—-‚e®ơÉ:4¿³6±à”s—ˆ›^j¸ÿ¾ ¤î ¦ƠøÅNÙEAçk^hUs³b]}ü…$ÍṂZ€ûö;™M2óYc~₫™cÊè„Ruœ1gû•26ïû9°AêS̉ó“™?~ó†h9uÀÄlJƒc¦IÍ¥ÓAZ#ä!•f%û´• ûê8£Ză9Œ¾}QQéàM½‚†b 5ù§Ï#¿©U,fM £Ä+̉ë*­|)D;yGP‚xHÁcu„jh1/ưR%₫º/­Mjˆ¦l:ó £"]8çDF‹‚ê¨?^lèS>>üĂ×p·á›Fb* ;/”6<ˆưĂG£áóxVè«̃æÏ”N ÙAQ*ê ¿8́w )Óßợ†utÜŒẠ%ù9$¨ál¶I{’Ï}¦Æ²cưœ·"âN ñw%°Ió‚¨í̉çñĂ,s9ü7rcĐÜ9=́çÉ~…´TOtsßĂ ̉C₫Ô B%//›¬=FvN°,hæ¸g̣̀mÎ_Ÿù™Qa• <·Nσ4,Jù4ÆÉC¿]Ô*²®q?%ö“Œă–Kúă:­‚o®ơ“¢±íÎăó®Zˆb uDyª V •‹æë“¬UûT î+'[#̃¥ưàÑåù¦¨RÀÀQ‰p̀ñâªbåÈcÔ.œ¡ÂøTÔD;‰lZÂPkî5é²’¹¶W~@è-ưGĐJIY÷˜8Ư %Fmh:a=₫úáÍd¦sEä '$!$ï¥ư«´ưó€Äö–’€q†ÙhăÀF¿ß8Ă÷6ÚYK«b£Ù“;!;2Ÿu(÷M?‘½†h¸Ÿ¤x¾̃“_ ;±H¬’̉âÛ·:¸v´­Â×̃™!±vtªªóT}%gˆNä%›{±mn’Mγs×çv7¸9m¶%æpÓKWm»ơy”N•°ç=\yƯlư(—& Ô#V9º[˜0DeaeÔ+‡̀¸_vX´·ë¼;"9 4¦ưrq †lµ6;Ö¥oă欒Yë˜7œ†áa¡̉<9æpB‰öÉ‹ªO¬ñ“>́± FÉ¢nyeßâ)Î{;¹Eg ô³‚U}P®}¿OsÏư®]éDlf₫HV |wă¸ùª­Zù-²dATå>a"¦ñ€VĂóS´&‚_åz–©ú&üŒû/‰“PÁ¯ë´Ù0ë×¹oøIÖj‡S®đœ“Ün|±̣Æp‘’‘©t¡±†V›ïßsàƒ¼.UŸ¦“öl&Bưz 1ZÙ’©‡>Fu²máD”ê¶ôàHÍê5Ñ• §°ẸÂ~ơâFÀª§ø6Dœô Û #×ä7ÎL]ëÆ‚ˆï¯8Œ–À¯ñFm(¤­\ ü¾~sQ×cÔ;(ÔceÓØ ơÖ'$ẮÓƒ=sÚX® ¦¦¡¡•krîYÂ"T§ °[ƒ¤ëäVu—Æ'OBb‹ø( Ñ̃.î¬,‘(7xÎƯPPÑ¢0e>?¦Ư`G/úy½!ĐF¹xÉ ÑÚï”ϳióÜĐê#)\îö0ŸÁuÿ  ĂœîÙ+’Ça„«p¨yYäÓßeÄ7“–¡ăW\2/ÈV₫ÖÑëÓVËg%ñ$vd“GȲ Ơ”Ơ](NĂíc°î4w$Œ‡â+$ ºèàÁïh+€‰FCRfÓ2\©Ëéh¼OOr{×ËÓGº§>Ä,bnĐIĐØR X—äư‘8r´ứˆMIÖŒ*É8¹8áÏ•…l̀ÖĐëêH[M¤­̉º)AeK0M¡‘œMà¢!ƒj Üơ.̀l¬%JgđüøT/ÙSY5ºAK H^+y„Y{–̣p.e]ˆ Û§CYÓ<ßbá…^Á®9Iç—Têư‡é\;Ü@ äÜg]/·ư­»{Í$ä*²¸Í1é‡Ư…K1¢[<®Ê=‚³‚ŸÉôöÙ¿™5Ȫx<7~B{µÅ5{/Æêẫµ†–ªÁV"B½́ȾBh̃Ú©„zâ™æđ.̣q­–-RûRöCp~Œq‹Ưw7 ×QLMĹ„¾5]›ÍæÊ_Z=.=ñ_d'º1c¤[½|ï‹ĐĐÜñ ÑrbÀÿƒU!Ọ~ÇiÔ{̉ROåƯ¤qdĂ%®¨­\yeŸùËoº3%åí y•·ö¢_ Á¼0ëû>ƒ:{ˆ5‚ipÛ•Æ9eŤªƠ†OµÏ&í)rºÄ¥t&™¨IÙ\xör溷ĂrÜ„….hk¸}÷Ù)ª ­ «Ÿ¨~hEpµơdayåÉjU¼ –€ºr› ‘üæ›5$£[Ë›Zx|́R€C_ïrü(aß¶JrL–¾sơ.E_‹q«>a51Í,ư!~o˜:)̣‰Ü <ïÅKN~0´°ŒGfĐSé{ÀĐ£•:m{ÑUûMêNß®&ebü ¾r‘ûÇV+/©Wê»×Á­”AúKiÿĐ8Ø^©ÛĂ´!ËÜ.b¾,À›Mø¨»c₫©—$÷€(cµF*Wk¶8e7XÈ;¸đ㔤-÷ó±”_ Ç0Á)Ơy’Ÿ1¬?$®‡Q(1Ù.d#_ ÇfzN,«e5).––—uBN:‹Î̃*íc˜ÜóÄäœ7‰ü±…3lë•gCøfæå§@ÍF*!qi$°éJ˜Ø]ZƯÓ²ö19ô÷¯¿½z‰OŸ±ô“:ü•ôíLvz¯6'’ÈĐË|x=ÊQ7Oññ¥;º™ăW{Ÿ̀-̃!?Toº-e<|uơ\ÁÀÜîQä’€€sr“Ë=Î̉ØèƠ}íd̉hMÎ}°? ơĂr« ‰Ă’ˆ½zœ¨e3]Pơ"ªcÄë¨a· FßY_ö6 ù]ZÛ'årE½’y{₫Ú ïđ>ÍqƯă›̣lđÙÈ[đ­*ùc6µ:ă˜â ÑÙX̣²¹û,=#Óuí_D¤¤ ¿+IZjiÀѰ„Úó#2Óùcªµî.Tz#DO¥q± Îc Ɖ†‘ÿXRùÿÖÆxßÛ¹¬­"×l̉Ơ·Ơè=reû¥Ë€X˜ B -Ư{y*FCŸ<ơÙHŒÏ»ïîÊùóqNUp‰‹ª4Eâ$ ̣Eêø™gŸ±đÆÛóÅ+jœå÷ŒöĐwVÆ|Ü—mtń5’{Ák|®æ ăÇ›×@fOƠÀ굈Â'IIÁü×]HºLdÎ¥KëµØÑ,5»=·ƒ‡ˆ–Ăe¾œ‰sâQ^ƒ„¾f=ßA"¢Ø%Íăcua@¥³*‹ûÇÙ $¤́cèhÑѵ â¾L|ö|÷̀ÛŸ“ÀA“xUNs¨ Æ‚©#Í&ªeBaSÙ<̃­ËÉî6ƒÇëé9%CPđ—)A8{¡›ª•ÂoôáO–±»3Àæhϵü#TÇh½l‹\ư97›m 7ÉQƒ”p˜4¼*²̣{Ô↑uÏÖPžüª!Ưy7,ƒZe‰‚%́úY\ÊG¬rèÀồR¡¼xƒƠ$"̃øÚzư†̃…ë%Ä( ïC̉¾³_ïÜd”K‡×® y”Ñ>˜(3‚mSæ;æ1ï±ß¢,àưY ùK­ôÙ@E+4”¸=|I² oizƒ<%«‚]i…ÑpÁ² ₫A–ËI,É\¦³3[ê詜hÍ̀° µX7lW¿qµy[ĐJd9ëW ƯJM JS襲Uæ„ÖF{×tq|`yå\uD|rÈĂ\AïáF’*áx¶zùʾ̣û“?¶>3B]+€}]~;‘äù‚3//yûĂ…k]2R72Ź_}-´´~óGt¹ío|'Ñ…†çÏ'¢½ƠĂè\¾,RY ³F‘6W¶À`«ó́Œ>¯@hÇŸgˆÂ|ÁJhÈyi¸³Ă”¦ÖT©h–AXê7º₫[B]K$ùơ¾ùưcx·úL³z¨´Al;ĂÚ›„ƒY3Ư'¡–.LM÷?— CÎ7¹ÎµPđ ‹Z…Í%hú1Z›’o%tƯçmm‚ø¯è  ’aWZRvKÖÍdÖ?P`(‚¿ö±Mxû̀₫AÇndI¿¶¹ÓJ7|xs/ 4ăÙpåE?²×3SOFµ¢ˆ–Ü£ÿ‰*²¥AØñ¨ơçT F;=ŒlH/¥ FúØ¿Ä>P©ŸÖ†Qœaët?Ñ¡mW~.\øÜ;1Ô[¢Ë-f¼A–ƘƠª`ßêS6¸æ¢•TơѰæzW]ç‘௛k’₫̀€pBÀ)v6Îơ-2Ạ̊€1ëØù¨ø&¡c™¯}j ¶E¥6œ­q\PÏ×sGJ;ˆ)Æ7R\3JÜK1HŒ.=›é¾T RØ·7ßaFæf~C°±"±§î̉>@̀ơóÊ=:HC"çÜ~+küA…Á~A  Óp÷“ÊÙ~AkÓ₫³¯­O’ Æ{À¯Owäú0qbmÚƯ€)ˆ¶Û*mpªïº‹uóT„úÙ¥ñ¤>ÔEÿyÔx´‘Cô t­lzcùhDú‘§éà19‚µĐ‹A Ü߯#˜q/È}ófØưñÚ­Åg;aÏT™XpP4U\̉ˆPñó;Bö€½øûôfcßOp^@ÊñmØFˆä…‘@Áơ! n-/¾KẼ”̣@ÄB—F+S₫F}ûnZNx!A¸‘°×¯í 0óaëgʇ-ó“)$•̃‘¤ÉÛTØ₫½w ²̉3+óºzđ…ó7ꌴW¡9 5dođVü!₫¤®¿„/¡e®êee€T®f|Ö®ص2„́À|2å|U•‡¾ˆ¬ÊÔåc¯¤°TºóØt[?Úmç²o¦0*å̉ï…mĂ²đtŒkàdf¤(?l»?™) chL]k凔b׌wí4’æD²jè©…'øđe@öPĐp¾‹¯¯ĐÓniHÆ[¥ ‰fôîô—tÛ~\¾€[)æ\(ÔS_8lÙ…’ëƒ)ü0*v¡ôy£Dô]RÖœư]¤æèŸVaê2ïA€æú ¨Fª¦E¡ ÊC“L‰ é:ïmáÍ¥ïÉzum`囤‰ưíHø­¤XƠàL„º :YBáwó¹ÖOơ™0_ 3nÏw`As8"Ă5˃lyKϤ‹×…vHØ›ßïˆö>́Á>Ç´®·ÍºẽûïXy®‘çM‚×FZOKïŸ^Py3rë¯N‘¢ăÑ#6<‰Ä)t· üÓkĐ"lˆ¦8— ¿—|L¥ÅƯ¨êeÓçûˆ²Ü8®₫E[1@̣Ư…‹<›y„«bg+±Q́wÜS6ư4L"DV—s-¾~&€ç_©çÔíßÙïVËöæÀ›267Â` ¼gÆJ€¯$íâlưI-x©‚M¾„‹Ă¼í¸± ¶±od–đØÚwCΨ4Ó/(”’\*ip“T>NU „ú˜̃Ç#h!Êá•LoråÀÜZ¡iUL½sWá‚I¶Î‚Đ̀.§øhmư;_ ˜ÏSçl~Y£‹nŚ́(°^ê øFb(ˆfDÆ áb£hZ';frSÓËÚfË7›ÁqöWJ?CR"È0!41h Ee;WI˜—¤^1K* !lü$aöSê}¡Ä²³€’ÙđgE˜ImV™qiKXEyz™ß_s&”M®z€ ”౯"Ççíá6w©‹Ù *&T±üˆjCÖ^çA $Í ¥.í©»!äáBĂØÿØÉi­+`₫+y°•éOß¾=ơÙÍÜ™₫"Gû¢w6‰ô=–ó£?æ—%¡Oê«û½`: ÍÖUƪ漯t.7í„qÂö*ô+ÔYxÓ3B A\GÇcy‘ĂÛ>'IJ â6¨Œ¦k6;#đí´Ơnl¬ïÓXX“€ă¿"v°L+àÁ½†ăQØĨ§B×…₫&î5ܑԱn£₫Û;Œ Ă‘8 .¼cŸºß„„§–öƒ"s ³±Ú@t+RQ{VŒ½F°üSm~O*£I;©·ª“«ÎÑÖ˜ÅĐZbÿ!Ñ¡—}*–¦"} tÇ#!ºèW,!‘0êŒRëGkäuV=¸]AN^Ưñ›¯R(­ävôÿá× wÙ¯,Ö-ă*1Ø,_2¬ÛhmĐ“~K27¸SËö^ûƒMS*&e)D5-½Ò ƒmè™Úæú.p»yÈÙw?-›Ê¯À#[Gq‡»‚Æ›đí²ùƠB₫|$đ®‡Ø+bJS2ÉI,ôăưÔ<ÊFߘx¥Z<@“Ùơu•aYbÆ®* 7oç3•ÑA­oA²hñuÈynaZ™‚Ơî³é;Ÿ÷'Ïz“1ÛöÅ•à”çòé£vÛ›Y‹Gë”4N²Lăñ O0ĐUá«3è‘' dºUœÀ{í)bÓ¶u•]Á²ÉP­C•¶Ă?r©Û4C>ß™úF÷!47=Ă.ŒÎj”̣5Óq6ƯÙå·ÎDơT)s7±o ¦ïôYjCF浓MzT È2ü̃ê‡k&Ơ].,i5̉u¬4ß²Hiד æ¤Ơlƒ]{ƒ²{d±³«qÏV«kÍŨ´¹ƠŒ²%˜YUơúăäü0¼?¬Ë5ÍRhT‡ĐbhÙuIN½ú=|d’øyDÿ4̉½Û¶(G9#„pqưT1„ä9 hËêÉNñ‡̣=€Ñ́á­¿·ơ¿mĂ‘ŘlÑ,Á•©àơÉ×%oơdU!ÓF‚ÜI;‡»¤ îơŸ()|¿w§;ER^Êäç’¨mBB%ÑqÁđ½á¬¡gxA¨u©ˆ¥¶‚±Ù¥º‘ç}–* å/Ú†ÅóBÖÜ}<ʼn³F|4'«óÓZ±W•¶äB±n®)0í¸JªJ>>°ñCç(7 {D$Y¼üü°YÛˆư«˜å₫£ÔÀ.?̣À¤bđƠÚûw ¦Tèơodz[$…²»Û(´)́Q+˜NÀ-ˆœß·r«ÈzÈéœÂŸÉb‚Ư¢`¬µºT=Jµ´°ÖBؽîän™R.C*ûU.äu“o™d%3K‹¦¡Äó{?Ôn Ÿ*mmUìƯg̃d»‹÷ù÷)!·˜'öo–ÁŸœ ÀJóH L´ÁƠo˜Ÿ₫|%&o “ ?ëzđY’ûÇưÜ ü{¯à¨}$¬øMF$2.|“Ơa­«î×àúÇ̃S63Ô ÿöJ~»Ùºêƒüœ>óÖ¥î±Igîñª̣Ùq³Nç'¦(&ņÙu… $ËƯá Ë÷¥el×PùEK\P¼¼fÿ›Û}xÑ́+¦üLø1*¹±™S!ÊƯr•U<[VÚv1z1<FÈËvPÁơơ;ر§zôè¶¥³C°4¾ø̃¿1Ñk=›Â§+F’Âí>gÉר$v[¡ª×{»¸ĐÅU£oÜEùö̉ë§ÖƒHơêÔôÇ[ÀDÍ̉áÀ§CX昄©}ß åǰ3n‚°ÈE¾u˜ª̉ß7ª"åG?n?·¢óÔc -u…h7”€’¨°{`ʪ¥!ă8;u:ÅG9ăFÛßÁÙT©“ĐÅ₫¢s>©wíXó$<›E—Ÿ¯e¿ß1,65çđíÏGü¤å©’MrĐ ÏrØC&3#nr•ÓÛb“øµ\b₫hnº_÷5¡KHXé/ïâzP¼Q® `yŸè;<´ˆ‹¥Ôå¦qéï4™ï¨@ÇâüOq̀q8L¤¼²1bTÅär áû¡ó‡:a(Ø“"’øÏ¿ơƠÉ¥xsä)«C¿]ç¸:dmù9=h¬B{đ’ÛƠ·íưAçó9µE€¦ ØuCg£ó"Ö?n+w³Iâ'X9(Úë³À®€;K®Q—‡ü¸Áv•|…âïH„Ể2&\lV!+üÛ7w;Âû”óXÙW¿µ¯9 I[nÙªÑ` ÜAȦê Útîzh¥‰((pƠÉáÔzcÙïR©Û)QŸTóÜR®nѱ£Áæºß…cû“ßæÛ#åOßr^₫D““ZĐöÍèQ¾k8…âê°`p"·æ ‘åĂ/©Çp¶8zvư)®ûÛ®̃æ8&ÇvÄ₫‘à_4àm|€ï¹èS¼ékÁ7¸ö>$ ¢ưض9_\8̣¢W`<ê›…-ùyÎZ̃61»e(誖ÀD‹g"…"aÚ˜/¼2kû{nwvÔu§©\ư¦Û±ăø¯h†Ëvz½æ̣ë"̃,9zîă–ô¢>í,ê+Ûù÷®Â˜³æ÷(䔂Bx€9×aîkq/×ÀFh(K²¯1©i26˹»!Û˜ź̉“eXăạ́ Ïœ27hsY{áW¼}ª ₫‡bl‡!£ăº€YE,ÎnÑʘ6́@–̣ïeæ¢^F|ƯY‹xhapN¼U7»́–LÊ¡óöHHꃩG5\Vø̀ö́ ±QBîW%†:̣=!ß;]æˆḾï•ú%m+ÆÂ3‘Ec½ vđq”‰«À.¤º́Tï% ¿Iç‘íë»ưa$óç.0ƒ́zîƯ‡å£ơcIuí›ÓÆå~ä@>S¢Aº́)e!£’Ll:´#ẻèJôăúÏ:ÑÈöØ J)ß¶WáºLÉ¢{E˰KÿQm¼÷!¸©êd’id@ÇMa“,ï5fíª­a—EKƠ 8£g„àKKÈ\ø£;Ụ̈H*…m»·ÀN»“sñmÔôÏzÛ0\%ÁçP#êœga€cƠ^ư,NÜèiF±)¬Â3˜­"mă¯8ú& ÿ‘̉ôÙ³ơ›UÇc–9«Đ~¡<÷c©Ÿ£ -MíY]T¾‰Í"ø6AÂÀ¨Ưöf:f¹Ÿ¸8™äAÉ"Ä,q/K†µ«Ơ|ÊüæEF”®_¸¨.3½1;zå!ê¸yênúfë{Ç;…7Ë¡ m¹¹3áuPœ™îµaÖg­ñI`₫óŽqH^³hJd{û²»5ƠÆéO|-Đü»”BKÀ`–Êa‹6‡¥€Ó…G³V¦úû(é_uàör÷íä1Låÿhă endstream endobj 809 0 obj << /Length1 1630 /Length2 17282 /Length3 0 /Length 18116 /Filter /FlateDecode >> stream xÚ¬ucte]·fRI*¶}â¤bÛvR±ybÛvRaÅvŶmÛ¶í¤ëư¾î¾=nwÿé¾?ö{M<Ï\s‘)(Ñ ÛÅlmœhé¸ræÖ†Î?m­ål9ehMå¬0ddÂ@'s[' @ h ˜˜Œœœœ0da[;wsS3'¥ÊO5*jjÿüc0tÿ¿æ¦6̣¿?.@+[;k Ó_ˆÿgG% àd˜˜[Ậ ’râJq9€8Đè``Pp6´27ȘmT[€Ơ¿#[cóJs¤û‹%è08Ú̀ÿºƯŒ€vÿ¨hv@ksGÇ¿ÿsG€©ƒÓß8Ù̀mŒ¬œÿIà¯ÜÄö_ Ù9Ø₫µ°₫«û ¦`ëèähä`nçøUAD́ßy:™8ưÛÑü¯`ḳ×̉ØÖÈùŸ’₫¥û óWëd`năpº9ưË06w´³2pÿû/˜ƒù¿̉pv4·1ư h@Sc+ £ă_˜¿Øÿtç?êü/ƠØÙY¹ÿËÛö_Vÿ3s'G •  #ÓߘFNc›ÛÀĐÿ3+’6&¶F†Ëí₫‡Îèđ¯Q₫33T“00¶µ±rM`èål₫†P₫¿±L÷_G̣Åÿ%ÿ—ĐûÿGîæè¹Äÿ¿÷ù?C‹9[YÉXÿ€ïÀß%c`ø»g2€•Ăÿæc`mnå₫óúÏÖjÀ§û“t2øÛAÓ¿Ô0Đ1ü[hî(fî4V0w22˜XưíÙ¿ä*6Æ@+sà_nÿƠV-#Ẳ)›™YÚüCë¿U@ăÿ\Á_º₫•?½œ°°ŒơÿaÁ₫ËPáï 8)»ÛưÍí¿W#kkü?ÿÀ ÙºDo£2¦^0˜~ ‚î1,ÆH»^††ÀF3ÄóÑ O)KéÖ´/J-³­×̣q¥X¦/sF›ĂÖG.§°n~"«R Hôϧk†ÄK¨2p ¥*j¨F̣N±³Ôàđ“‰̣!D Tû”₫̃(ü¥ÛæäMÅÛ R¡œ̉W“y¦@;ÈkFû‹ñĐ5ẫ‡A@@Ă"äÇYÔ#äëÏ–h₫]œoIơB¥峃+ü) ÑÈU®̉—{d̀¯Ø¡ÈÖơ„\Q’Ùdw^w‰ºM]Z)¢¬đsüúSG½ởE;Pîuƒ ¤¡ù¢år|X5Ï>æ «êëi´"µ·Ëp3Z…’̉»"Øvsă§¯X0vÉ]øUr“FáCÜ",梪Q¤F@ôèM¬N¤*Ơ¡kÜm‘XZ&µÏ¹¢Ößb —w|ẽ'Ö!…ß¾©ú~û]æºÓbINf·íåâ’¾›“]N²×A°đäÜƯà™©1S¨mW—j·>ạ̊=c-)Ö¬ÀĐrب_- Uy‚¯C±A ·Ä-ÛÅMÙróQ&Cq̀(C¦Å-íEƯU!nLR¦>à+Q[(“)RÁjdị́G/Ø­ÆQéÑÅ-Đñ!OYDĐÈy¯$‚x'xQ ö\AŒ ÁljüK/(kWQàû7ă¹Uđæª‹ÇxyÚœ‘ưKfG=7s –(A÷Û˜5S¾ jh¾sÅ$†¯ù\Q¾ \Đ9¬™`í;Üæ‘ĂĐÛƯ’́åÍy¹*a„¹´î])m:ŒRZ›>nNÛcF̉uußMè¹eÓ“«MÉ̃À ‘æjé‚Ó‰ ÿº£¹§îLUMc”r†÷hÿÎ0¢0,µôo“ŸÚÑ^ÄÅ>tê• Â…›ïÅâEÔ±Û䈥%ÊƠq?°<&©Ê-¶ 2¼mY'Ê*˜TÙÙ¸ó®×[?^c^]ÅÏ̉đ'@©p»™Ñ×ÖO½kẻÀ¾„[àÑLcă,G2OW³R³Z%¤ø¬°¦¨÷jŒ ̣Ù`ïñ²‘¯rMj¦¾/Œ qÄƯ«P›ö]ŸÏ/ø·ÍĐ–ÚhÏ^"ùËô±„`g麒¥đ|ÔlA^+/_„̃™5JOü‘ç°«î)„p9·´MÜ×âS2ߤ% cn§‡KÆvÔ,Á_òÊEsEH'vo₫`4WmÔ² H©]ưÓô{O¤=̉`îçªjnlá %.¼éüÜ»¶»>ß« 'ö´wy’wµjđÎ.O~S‰ư₫ xQ¬­;o*R)LŒ(Â₫ë…bö´2‹Îˆ#₫,35¢¯nP¿Å£çZ¬œÙ”‰Ø³ùÄ]mH^xŒ“Å{S~;à)Î(,ñ=̣¶Ô¾güóX!o³ <±ZE\0™»́I‹>?½ö´?ûÏMê-‰$ ™²¦ÎùđÜØ™c¥¥¡?HÏ›lxb…Z•'đËf "¥|Uäî)竦Q»ÏÔs=øC¨<|.đQ¦§²¯EZ¢5úé\óÊđ{2lm>¯ÍlÊ'µL>TĐ€ƯđAºœºÚ“H,ưL!*Ѷ‰¯Otvÿ^u Ç}‰¨Rñ(_(wAªä,́Ö(Œ¬±~{™ès9/u“́”µÿ;r– jMÀèH vw.;•i-\\Ô¨ÙddêÙ&t¥7¯©­€—ÀªOÄn˜Ô— @ÿơSX¿Ágô÷I¥ÿä06 %äKc'₫µ¥đ³‚z¢ûW³ïwÂư•ÙÇ3<Ó£«S±k‚J:C̃œ7?óôé?Ó Bî0‰ÈIÏCdÍ–w­Uª3†ÖË÷‰ ë$Ơ¦hw—„52'Ú`1ª9^,düƉzv×MµNU4́A uE4¾Vü=ƯȬ)­ë’6-%LëÄ%‡†~Ä£H$Ă6N/H¹:xD‹£†c±KÆ@OLÈeEà=º"(üëÄ™CD¬V‘:ü†úă@₫ ªn§mœC7;w0ê±d‰0 ˆÜlÑ·đÄ̀¶O$³úua¨Ơ„”̣ «Oè!åi‹ ~À½W‘LïSÍ=¬¬̀tDy,d©ă«b,ÄÛü/‰”{Á#ÿDUä,”ËÊ®Ï}ØNN5₫3µ®†gEăM¥w˜ư´1<̀8˜¬̣¹-oC™î#L€ƯÝ·óđUûª."qLqỬlnªzêG†ÑÚÁ r…rƯ=™p"pænV#L½L@׉}́*ơ/ÉZj†˜*YåÊÀRoA­ôm,LË óûöV.ºRMh>å@A*zh®˜ZYÚo„Úu€ijÙ+/ªEƒÊæ6&óáöîF¿Ê 1[HÁăÑyâ« ñ̉ư2̃[ 8÷µ±— sɯ!³Î êˆ?ky`ùJ”®j”ÏtPúÑ"…]P¬!± Îe V́W×¢é÷:0+èä‡@́ÜV|(¢Å ư"³´"³ôN*6 ƠÁp”N6§´ç4óß6’È́7̣²ŒÓp2@:³Iz3<̀ ,n®È*ñ̃ẃY˲ £¨E‘ß!B¦¤#7ªơ¨…G9•&°slÓ~ŸB[ ¹Œ‡Ÿœ­ŒƒH&üyT–³ «cx€ !­çWzHliüÊè”Ó9\F¿´ÆENsp$–) đƯ¿XAcqs?’î΋döä¥Pa+JIÂÇǰÂT$ ‘okpá₫HI*+ч:´ ¦›,Åơ†»&(1¿ü.†‹â8Cd¹b2Í Ïjm’Èñíơà9#*0íçÍ́Gq³¢í•±œé{w‡A«eú 8Q*ùŸûÓø:öعc»höQû—f¬ÊÍưEé́SÓÖ¥C·ư¹¼Đ2qæ-Ôg‘RíÎ×€“ú¯s¬@ÎƯ›6‰uÆ2R¬kó ˜Ó`5¦ ïa‹Ü6¡Œ4‰R#[7 —ö,™RªójV®‰ó†»Ù«£ |êök…găĂZb$ÛjK!©<#œîdGW}X»ˆù¢2MfêÀ®K—p Ă‘K»÷ Q¢jOô£ú} Ö¡ëâRÑTÚëFkP><Aë:¥‚s¾Đ ÎŒíaËK‘H¾¸x §ßµrË\n­"hR¦;f¤A‚‘>)>\Ô_‡æÆrxå{Í.§“•`¯:™Ç Ư¨p~êoö,Vô-›MùR›6BN¦H,®ùD%¥ä¿@ê4‡“DæFr¥Âï éNAË—§F—Ê'±Ưm¨üäĐÍ?N1ÀƠä=éî…¤t»ƒw$«XÂ'<çeƒÉă³PlÚØ>OeNd!~¥ơcêÙpA©Œ¾u½œ¡·[¡*̣D@R81l ¬³GÍUeă]Đ4¤Ï̃¬âaJëζ3&éÆÚ~ă*9äüu?Úc¸ú¾ùYà\ÙÏ««8i#öK;¥₫dä„.•Ú`Üø{`aĂĂ)…÷¢2‚´±klø“%üYĐœ¯²z C¯©¶4‚ " Ă`hüŸÁÉÉ\ër—å×£W‘~¸•w‘4=HƠ¥¼„‰#ViâÓFi"LélÄK(o¡–â ~»µ¸è4æ©z¼¤XđE—́đ¤Í w₫K¨Íê_ÍW*s „Ÿ+ öèL ñ6~?Y1\AÀ0/Ä‚U­3â~LÔ{œï½¸Ùˆs†ÅơK覅¢3¢1ác½¦±s§7Â#Å© ;L+Ó¦Y›Y_(æ÷|¿Á©ª±̀¼qÀi{\í‘̣{¸d@@ºĐB ¨‘vRơö賯ÔZ…Ñ&›rÙµ₫½–>ØFèœq¹m"cü†I0kƯMÖàé˜V+Q­Ưt‰flŒ±X̃‘ME…})k¤Èí™ <íñŒ£ÜRóO ¯Zw,Ÿx@L‡™¾ư½ö=9Éå‡cƯ¥—§qGW%‘Đ¢Wr#»ºFÓÂÅiI=®\ᜮ¤ V¨úe6³É°RÖÙ$U†ß*%¹¶ÖûO‘á#k¨tOơÄ}.è!<́øß*‰ñ* `¤¢¹WD‰ø;ïØTqÎxÔÀÇñM­fÈQÛ"»çúKṆ̃ơ³€t’pJsYâ8CùưªÖA¨(Rµ¨æ>Ù‹(C.•î§dz:ÓoÙGÚœ$µ0ynµw˜¹Ÿ8’Ya”²ô}ç<¨Q1Ô‰n<¾êTæ‰`)}ºazrÜ5œ%œ¯3¡ơüƒRíC~Á·ß•[wиÚmy˜ÂÖÀa¬ÅŸÚåÅ{¯U°qf]'{PÏ0›đ³«Ă?-B5XO£ñ ̉Övˆ#’‘ÈÈGN‹iR¸p5=®=©ôú¢™øÔ‰+Å pës\63J~f¹ç°"‡WQƠpgƠ¼x_gcïeÜĂQV3?Aí¿ÏhŒ>93é<Å4duŸădtçWÆßp²Æv @Í_íˆ1rDp¼ăúç&¬éhLAÓl7T 1ÇÆßđ¬™×Vc$ÎæRWó$˜{"̃l¤- O*qAPv£æwkǘ¤Y‡ª‘R%ßg÷Î?̉x¾·&á÷Ê}ŒoÑ1lXF{1îƯ¶¢Ú\N_jœ­«R8²Ó×Xf·wRPV~«°â’ï iè¶præƠ**ˆ¾&’PÓ½¶Í/&Ïr7j ‹ë­…“ÉđưEú Ï.}’~ă 8JsIâ÷½o:M7¸àÇAOä\´¨wa+µÈ,à¢Î]I”₫Đ²;e 95íió›ƒè¨u#úÍAÂwdÊ]̣߉›˜ơlf )äˆI¤f̃Ø©?[u!“l~ưj‹Z¡.*§uùSqÊÎP"ç̣q(×W¨ÍăX¸BëªC¿P̉lÙ¡‚ÛrR…©ïÖváé_hÁ#îƠ¸€Đ„œZ̉ƒ¹iPD}0Săe¨Îü"4HNF•Œ8c]:1?ækçBT ŒƠ $pk8ü[»+ßh Sù­e¼Ù:$ü–@­yªt†;Ơp7rwW®Ië•J¤ố±!|/P·"”l”.¾ Ô¾‰xavOœ·;rjM<峪Œ)¡o"'ç} y׳uU¨td€ÑîÛ¢̣æa₫Qƒ¤äëë#*'ƒ~8­eéHÜrÉuœÁBC¤â.RâÑŒe,qX†ëÅjâ„{ˆÚ桹ĐÇƠ₫﹄ŸÆ´&zđùÄỌLD̃¼.­üZ·Ö­g²²g}Œºë©v6èVâàúH2É^>È̀¢Ä‰&º¤wÙ|à6œïÅMÂ{§h0qŸ22¾t˜©ăË₫(®¢ŒYG¶ƒĂ‚ ñÎ0́Ö`)«‰[¹fy8ñtôEvH΅*¡cFÆ'ˆ1·¬¾&æ̣?–q™0Üđz₫Ø4uJs«ÔJ¼…Ø®ø#¤Œ¹aÔ2yY’ưó¿Bă åm£¡¯̃΢\ƒ|Ùïfl‰SKđˆnăaO‘“Đ³ẁ<+>À8Àܯë¦h6QÜ´fÚèơ“q›©̀ fœ’À¼œǸJö/!²e๗$9̃¦‰ù‰óeWÿ¨-®¢ÿ)F·``G–1̣°H\Z™È|<׺a JI@8ëE2×j“̃hJzv «5[YNœ~]lö1ù»ÆđĐ; ô&$ÿZùÁB”Sºåg¡Ô¥“$OĂ6*ME`±f́×ûIªf é4¡ªW*ÇD&ºD¤lPQ®CŒÿ|È4°yÖË|ë M¢ˆ†Ñ ¤“5/øéX÷ñój$̉#)ŸL“äØ"ÊJr*/¨ ‚XJDË£nG)Nê…ôÑɟɤ*d)™3Ê#̣7lÊIpñ}:ÏỚÔm>ẹ̈.îf¹ç¦ÓÚPË?u*$ø2WÉ':‰F:ñ;„”̣dcĐg:“BÂç1â¨zAñÏ’ºÆ>nÁ>g0¡rƒŸ!ûåàµás!Í´ Ó¦;96̉ûëF#p T’ú<E…?!›T}Đ́QRåÍ>r@t?€v†-x^)3î¬́º°Y¨Ơ²µÎ=‚‡̃Ec‰kWÉu¢;Ëvœ0”IQL¯C̣- Ơ«(2ơJ66wqă¶`I”T<\§‚ʶiYˆñP˜mÚcT?û¦ï*t ˜æ0V)J"€ÙfœÓ%́̉u ù1ˆaÄs?ÂhËŒ…ÔJfë̃mɵ̀¼:RƯ?‡YµçÅ¥%˜²gØ—›I¹̣$¼5î»VªR}íD¼­̉•»T̃>»“gÑ#ÅÉ̀ êe¡>× #E”Ï,"ïm(äª{Ÿ¡Ê˜Rơœô‰\3rœ\¤½¾*äkf&akÜÓŸ:– ‘ïËqkÅx3{5ªm™zF#ÈÎl‹¯?úæ~̉ñæ>,`v2÷ÛtÊj©M« æQÜwv ²€êMnlM„ƠĂÿ4΋‘»ÄÚRôđåC°OÍ$ŒÛ „æ®xÍpBæ.êñ ÿ}ªăÚ7îAèMü°MNz&¹_ê[Ñ+́£!&¬x4Å•¬6†·UqĖ膾} Ïp?)=„WÄ1Ë¿Ư‹d·që_¾¯/bDă3'B)"dTä`cc'•‰ó@•-¹x+a, <½(ẨC°}D¸ÀˆEà×&_°}ÛÎÿå&̉Ég#U Ó₫‚u56Wzé³h‡Û4_ưÎ)H¸ë%O¼ú˜n3TăJv½'̉<Û$=v¶‚\…0d…zC¦¶<6†ÛèÎü La)*\[ù]OĐ’€Ä“›€l¶©s₫‚Ô4ǼxÔ£×ƯM‚ ›ˆO_&¢x¢Ê‡ƒ=…fÓé%"5;5Ög{Ó‡(‡́熓`̣A‡ ˆ«ç·€+RïS•ŒÅ_×Gú?êi1ªµ‹ñâĂÎƯëƠ3¾ú0¸đ$1:́O¾:G‹̣¹K4ˇTơTNŸ»s€?¹£6ïFô€/ß æk™^Bac+B#́e$ŒR=ijÇé |ƒË‚Tx2.- ONI¸ê—8â¨Æ‘]N^E)ẉäO…´ëØÆŒBPVÆ©kïL›/ûÛ`¾¹‰V‘₫©ũµØG‡£/8ÏbeÅ₫̃̀tPg}¥3ÅIX´è®µamu¸gùÉ·:7¼½˜Üû#ƠÎy₫&±¯,f|¾‚O'3–D·»rÁ]“<4XE1(OÏ»H@vƯ*Ô%.ÀyÇ;Pѹùd±t#S1èj!ăP”;‚HOZúdÓÛEĂi½Ø¯©èµéJîBÿ³ ‰]B¦e9Ø®ơ%Ÿ×ùçc8Jé¹¹xgMC¾¹ )¸[6²É¿Ĺ3Ăy¾æTzW!2wü,ªù¤ỡBña×nµOª;¨±BEißieLéÅÄ ß øœưæ& ${©ôƯJD@RA½\‰ÑÁŸæ¼ọTá7’y†ù¾w @\ƠU-©ö<λî*£©Đ‘×Ù̉ b¾-›°ø*äG“̃Ov]Ù´µ+Z»œaé‘É&m_{BtøZö%½Ür\±Ơ’›|™ùUˆ¯X[‹™aRÆ̃­Iµ¿q±;(é¯Éëfg:̉xc-Ó^΂F/×¢¡×V.fy•ËŒuaPœª?é>c«î@̃Âs/ Îa!zp6‚ÜfƯGEæ/¿ÊÑËEí_cwë²è3Gùgö½÷nƯBig‡ưù—Ô»;– Œd1§¡7đ`À ̉o%nẠ́Ùî̉c"' ̃đ†i\¾`—`aâ™K7Ư`ë¼—n}‘çy³CÔnÿQß!ÏS´Z½Œ›*ÈÊă¬ÿû!“‰<눃Qôp„Zï*¡Xañƒ¨ĐbPú‘® ÓzèươÿJâd踗4%†rø*nṾcÛơÚ×MÛ́ơhÍÊÓ3´ v.Ÿ|ëˆrx«ßg[œ@àíQ `/1úO™=¯3 îs_këư~‹‡xưÊÄĂ¾²\ä+ØÍr[ösï!©û†lHkÄÇnªEXûG+ö+p‹·Y½Ưûđçp̣f`Çd†¸h₫ÏB$1C|6AưƠHC»¨‚fóoŒT’W‰ˆÑÆOD#˜^v1ˆ’3mªØfƒ‘}ïEReP©zXî ,²¨ƒQ₫®á:TbÑ(£¤ À/*§·‡"ût“R>™'ÚÂV‹¨‚—i-½È» ¾¡#̀¯ơæåØY z N«Ros¡¯x˜—tÆ%ß¶JÔt†N=# ’|øÛ̉­±á£ÜCËaî̉cLư6μh0\CT‹o%đ&ÎÔvó-ªA•‡è¨]b&:›’å£ÁV.FERw×……_µx¸ÔƒEv+´¡½„X,U1ú-V×Íj¸AD\§_LW}ß»µÄΪdÉ"¦}%ÿ˜ơơ«‹NW¹Ú ›¤ûŸ–d½ Ă₫â4×6#Û¢iÿSË€CÙ*‹vô:Iêè.Ưª‚ó3̃¥Œ'6*¦.c±´(–?bn§íXÏÇR)QÊFÙ₫y™Er-Z´“:¸ÅUH̀“]¿]­˜¾oÚ̀Ơ›Å#̉„%Ña ÏáäØà˜‚w¹₫knIÙä¦NÇHǹôÔá*Å• u}·ñö›É 2œ~•GÙ,ĂZÚë’‘AÁhK]Ză®yÿ{$³ÁƯO/ßÇ̀2ÙŸ¿¹`»øä®ÜVÈ…^OÚª9:Î\áÁư- Éè»́iå-JßWă|¾D¤đ ²yg¶¯Éß¹fɉ+ÍèÙ“¥ ₫¨ÈïÆ0¯?­ñ‰—dDY)Ë)"^{>[wj÷ŸJÂÚd~x—æ¶áÁS'-ëvîĂđXÏ¥!t´ï-Ơ Û #í(K«››h´é'‚;’À¾ë¶4{éĐEoØÑ#Ÿ÷¡4t^ †œYêWg–À¨ª]}GHvÍñ‘E-pÖŒ₫°̃rñ u—Úï?ê}̣1Pgp}ƠÙb å„} ½nÜ„+T÷²v|#Îë«-©kµjÆ’ñùˆñÉ@2ñ|»7eT4BÆPPG¾ºÏ¤.t´tFå!°W>°cEƒûB¼÷́¬Øäá>¡½$ÑV£Öeđh°̀¾¡³Û#•ȉJ"©VwkD=åÙMßåă¾FG|.á.ĂSÊ%T?>m$Ïœ/cAỢRà·ºRă ·ŒÖœ`3ë́Á4H切hu­L¡Ô) f»ûDtñ8jj-j îµCƯw7Øe.…\ñêØPb&ksûè.nƒ"́‘·øT ärg4ÍÏÀÄy/35%,|[&†bÏëdr¹·\V3BëĘîÀụ́†ÁËGSf#ö„ª v¦àÅ8„>#ÎĂ“”,"T Q $ñ ωȶ¤NͶKÁsbH´ªgÆp¨6ÜJ±¿Hư›G`jÅhaº±o8i,déP hS›|ªiä!§$>¾oˆl¾Óƒ¡˜'ZÎÉ^å«?,ä :®«^,0ø{ktj×™AéeMùA-_ÙQµ”Ú=¦ưŒ+̃臿<đ6†Ø†QèÀañM¤¯Ó³Äÿª­ É~×Zu/á¹"úV•ÀÇî¡°ç1„¬;Vùc3đ{0öwcÜëE»=V²dC—év·jçA5„”# ’®"Ư7¹ï¥U {₫æe¿½Á2óˆ¬:f́ó‘àeÍƠ§d9¤mÅ #P“]áíđ!Œ̣=coÂÛúûư¨‚L:'̃©zÄêhƯmÊ'ù]èg^4K´²7#*˜2»ú¡<Îkù´ óH [,8°æ̣·áèÛ^è2¶Øæ0°.âơѧœ®̃ÊÙT‚8‚zßWË*B9̃ygÊnTÚÂÉË.¡:J́0*ë!¶nûsŒFåz¤¡‹ß,û£¡äG£ Ö­T²!GÀ2Œ^a§3ßơ`²²îx……n•§́Q!+‰Î3_- ¡Lơg´D€l)º˜Àt&Í uœÀ†€÷ø±ÆqÑ;."t?³wϬ˜)ê´–L Ó— 6´2 JoGØú~Z‡)¢qÔP¡ñÁfăªG½ú‡¯G₫˜__€G#& æĂ‹‹Ÿư V=̣́C'‚!MƯd ønnêɽtæªÙƒ̀S£Ê…;:§fÚ7FXđ¹×&MÔVHØbÄ ï‘Óø|’Đ™MZ·®#5^.k7ůí.—tLµS¢{ñƠú÷¬'¦µưÍ廵@á~m»É@‚=G;QµDÄa½·ŒÁ¸cÏÈ£YY M§Ÿó/ÉIH!¯$Ư¡ ·Ij1wu5₫Ü]úï†\I¯2bîÂằ#¹úr.†’Yùp3 0Á2”Øö |fÉ!9-uï˜ÆdM‡ăíVt©ÓŸtÔđ¿ß•ë:ÉăÏí ,°ươµ\¢›!mĂ­½w…Æd¬Í‘ˆ^æ¢Ceú#4‹?ômzgqT^Cºh5_,"Ù’øî„:A÷ßCưD§T4˜¹)¶‚X}‰Û|̃«S"» ́Ü?‘Ă"¸ồÖ+Rï¸Z¾uÙ.ƤÁ\g#‡©5-Sô| ĐG£>ǻy¯H=âß7ôQ"YG5̀k§n3t3’ljca",`>ÜåV¤ÜürƯ?±ùxwmI"èƠI?ñ%8“dip¥óđ£à'Q2‡fDto´)˜ §1‘x¤!X°ÇXj*=—{Ör\:éèQ”ChPúđ2ăÛó˜Î̀~NFxƯ˜-9¦sM±£!…ZçÖŸ­ç¹È #ºâ·Ú‰aN”ÎB¬dº¿Óàø¼3ôeG¿ötÛrƒ¨ˆS4Iäÿ™ÿ±ÏGfñ*ÁFè¡Mÿ[n—Lÿ%#äÊée2:Ù´À†ø‘U³r,cS:¼UâO‡ÜAaËáhµj ¿z3n ̉ư‡Ç<Œ"ÄHå%Í.„@B¯[;ù̃3­î₫ˬ̉y‚²»)s2£7 ,Ö*Ô7eđ’EvL!ư¼-u0K ”?đÖ~²˜ª‘`}êê‘43b¾v¸É(¯8€e‘ø-9G­z{!Ă ˜ZÙ¡@°?g™$'Q ·oPKÇyBáç4/L0çÛ©ñ’De¨Ơf÷ÛAø!\Èd’́ơüN!HÏm\Z¸E˜m&€¢2£ tVÆi@a"¥uÛÿ¶s߸ù\‘ü¯=ßư 8 ©y,+zè׫₫₫Đú ty–ÆøƠL; uĐe ƠíÍg‚"„Ö÷Ä9m1øKú®C‡V–|QÅÓy%ŒƯ ë̀që÷1£:ÊAWaêăS¸ẶjJêÆ M±–;í~œđÂS ZpÏ0n…Ö r$B̃á`< æp `vüó©jnƯ.]ÖÆ¿…’º‰³Ç—¤sàĂdUà´J9?¾MùÖÊÀp) {ÎàgÇ®¾F5×y/éMé•CƯ ¬•@¸—É5ù Â wt'ĂÛJ™¦c£Ôf!ưà…ŸơƯ1"O‚iY…)é®́̀0ÜC( zi’~†ç¶ưÂx´ôvRŒŒx)¿ê‘h·1Øÿx˜̃1—å7_‘²r]~ơ%ZHƒJFtD«iͪ·7ụ̀={͆́Á sÖ+?ßAÏEË%€/˜4½hàÇ•'ưǶ„‡|,à÷¬eƯ)6i‰₫ á8é4ÚœSM¨\đÏ?ïvÛ€ è¾”ĦGûja ‰¢NöRî Ù®°̀r—™]̉Qñ)p=&í‚ǵÍëA¤"•D¦(¹Pù¦ƠÄZĐbñ±‘XáÜ.S4ïÆ"’i3uÑçUûkfÖßñ˜W9Cwḯ¨`UÀ*P}îI•61b¯Æ_±¦jI‚|ẁƯYoÂÎ2]ÀÚ ø}UJp]óäûđZ˜³¥÷?™’3Za—´¶{aN™›£n˜•ÔTŒaç¢>ÙY·w̉Æâ[—™“vFÍÙ̃¿¿˜O™ü¼IÀg¨uwHè¨Ë—_ù§₫đ'¹,4ud›̀hY=Y£ü©iZn+yá˜SD:£'v› ‰“Æö½°ó‹XK̀Í÷qjÖ÷öE@´Ù™C&ë₫1½2eä5Æaߥø4¹M³K?3ç?‚€?s8WgT-êuÑ1YóÄgŒ¸¬“ÙVy÷ƒdj* 5ämĐf«ö×ÈđkäÇ%ʧÂ]î_Â"£ÍS^¿̉5‰FÄ¥ïB’`IfXy¡›¾G­5¥Tôá•ÿI₫¨1fl®»º£ñØÛ›°ơ͂ɷÈå~‡8t:rü|ߥ*zÚ°‹—¸ñ¥âœéâ…ØóW;Q–_ËĐj¥Ï¦ư&¯®Œ–ͯ£æôƯs[\‹º}I‘Ôbj¹Çû[&¨Tï~YBa\ûEúàjgƒñ®ÉơămVÈÖĐ16•çmë‡;¬}–2âÚ´ÉÎóØæ¾ ˜Măb®·|Ä\êËR‡b$Ev¾¨ß’ŸS^ C|ÑQîÖºđå̃Ơq˜ÇåNzZSËĐ&¤vƯ´œÈf+©đƠVJ3°Q±ï3›Aú&|ÁhLô¨„5b1v Ô&ܤÄÔ¨w—_¦áÍR£xXØÚOµ0̣0±ë µ­(ó̉Âû/—ån±\xσß]?îˆ(´E¤í¬¼ơ×ñënÈ2w§¢h¬¶t2“xs8ÖfÏ™̣†ñ„0‚đx‡s³io9W3³oú(,+z°·́ߌy¡œ/ħwÇ̣BeLJËW2Çgú9ô{qK‘‚Ăj)å•K2¤yª N¦“5ñéu^̀ü*¿%"¬¥Á›qñE+ˆ.àuF&s† Mjª–|I§ØÔÆ#đÛ@krë’Ï’<È»w,~ƒÆjïDMFT%›c¼‹Ù6©[ 9Á"OkZÊÜ¸ÍæE—Ñζ¶á&J=­6o g?R[áÚ°ơU(iŒ{˜x*“Ç#1ŒQóßÓÊ!Ïœ“§¤•ßSQ¾T›¬w÷ ~‰×­Ë":‘øÁ‹5¡édtMH=óhœ¡ âÊÖoD7–Bö²Z£¦ÊÍƠ@O'*É£Áó”·óœ#ă5iÓ hb! Û[̣¸bfÀK¡6 8H MÂ`TÍOÇ< [_°É!áߪJí…O‰ |Ằ765”¿V×6ÍsïÇ®M£)ø@樧³®Jo‚ÙGû¾PPñt§yut†r®øyn7{„£On¿tø…2V…ÿ'ø² ̀~æµPô4L½̀í^´ ­r¨ß•§wùĂºQüÍ l„âÁ„@0B¯̣ôH88‰[̣-À¸‚À‘b¿©ú»̉T̉v­s¦(WE®(j––²¤0“Ù0µ¯\^s¼*G¿i9åưé¦₫øXô»SK­à¡÷wyOí°ÜØ¥¡;•‹€‚èv»çâ7\A‹juö¾̉&äÅĂÖa¼óΙ¹_7ïm=25©¸øD‰¥8 +vB®ê5Úr¹ÄË^–῭ö¡•*ê$ Ÿ’Ç`Eö®º Ă?i¢™̣‰˜öëá‹r1 ]+4æ<‡½E„t_!Ü:9yª‹` ,Đï:6₫zz0,9Xîá8kî²îµj”-’C‚ü!8¡”q₫®·=>j Ç7´Ôjú#ºä¼D ϼ$ §K£°L½Ê#ÓqÀÈÜ3÷u] [Ù¢ï“%íÔôóÙŒP̣uLÈó›¨!Á\7Œ“!tF¡·m©£Úñ̃¼cĂY°_Ø„éô™Ü“92f­EƒĐG¨‡ơܰb…Ư’¿<¾Ÿß…¤?ó1o1Tù̀É*E]$Q™áJAPẸ̣̀åUÑ ̀$±¯sđ1˜¿SrÊöª(ûëËT€¤`ˆë %û"lÿư|½™n$n±’1 >¿¨6́Öʘ „œç3!ơMjOƒ×™¼́]^”Ô&î+$]4®l÷¶nºî¡.‡øù;¯#HÛ%C@kW*eŸ½ o9§Ô| 1ö”O¶°â¥üo›vÅöêÅ•¹ËÎ'e¢.ËăCíª‚|=–c<4j¼~>IKÛµȈÆö¦nÊS̃Ñđ^ΤơÔ#Í8NÏ̀/Î…sŸ 2}™¢BÈ×éòi° [À|ö"8B¯+éư–àf6âiIô8’Ăs”È^ª§Å7,R·}!¡-Ó¨Ê5Üê£ B¹Ç„L*%•±bK¥̣ø ¢›nÏ8RoÊ’Q:Ÿ=Ü>cú̉6¾ΕeJ₫Uå^B™\°T¦Ö 0#3Ÿ§äîecä€løAèØ  B›Yœñ€U]iq…ÎeºVLŸcmŸhÎqäƯ-ºÊ aơ‹–ÿ¤€ü+~ă%+ëAn.â`Ï:½‘6†ˆíó1´=ï₫g›+[iB¹êAË+½˜Ë,;á‡)ƒ±1¢"mĐÑ>ưs`̀ÙeÀ¤Îg?X;çƒĂû/µé^ÆPÄöRv$‹C§!1_zv ƠíT‡É¸}¤›‰đµÎĐrÍ ‹7Aoă¥̀Å­~l!M:ë>ƒªéϰÛuá!L+o«ÂRöQGVírt¡́eC雄¦wÈ*f }Öù‚έÓÔµÂ9@#÷uâ₫ERGâO6¦¢yxàh5¼Ÿf‹ØA'²Ơ3rY¥ 2€©å{y±]úæ—Rj–'‹SºÎúw}flNé̃…‡¡'T3®º]]±¨5ºK§€(lă7çpØuut÷K7ÖæD°cæ|°Hm¸¦}ªUơ$l‡s¹&h?‚áÂÉÙÉu₫'¾pVI\ .œ€nµÅWhKV~O~·.ơ'›ëÔlïl^– £«<ÅÙc¦̃\ B>'bá!ÎNÛ@Ü~ê§$lÂV³Êë<~s#'q]è/2Çđûˆ'„2^«n÷CƯêđƒ™¬ë‘ï–î\¯;e²¿ÙÙOÛ.8rL±Hê*Yxu»SfÜ-ă}$ɔȃ :ULKÄÜ—Ä“Ø8éóïÇRyk‹Û¿§…[fBL?Yơç`!Ú̀ûºHyđQ×o~sB+$LĂ—Ë®L)#¾€Á́g³M"Ø€!©™kD ÚñÊÖÏX8ëûơ|‚©é 0₫ûƒ?äzÅû)\\am¼âÖWÑ1Vav–ü ɸñ眀ûí:Ñ ³yØÏû:èXéqzÍtøt:ȱư›ïz{í’<ù.Ñ‹̀hÛ ²©M½wƒÑûúªåªOư›iQ>¬ăP„,4]}i½Q5&ÂĂ4ö]̣§xå(>°!)Ïûr1}Dª́ŸÅù…k©°MI׉{ô/°í_óđ‡¦O.!™ÆAöư½&ÈĐgÖê?dFéd t!^N°fư¶§ÜX]‚ ¤"®ÚªlRØRMœ¤ ‡4f:l(7IÑÁ2[æL4µơ†®LÈ̃căæ/jđRæm7sµ g^$Ü\‘8«Ô‘JÎÂmưù$° ÀùÉIß@̉¯–¾&^)(Oø‹ÛcO¢,6È™e¼8¬Jûl ³ßW`hEAÓ“'ê‹+SD°ê¹»o›ÓlflÁ,¡?3› îÍÂFÔ8̣"3û'¡ßíä½Ưø8Ùj×Ǵ¶Á4üẪ Y´‹Ö×̉ÔÍ‘Bbb₫í”’gïǾ­ †aÍEf8<AX¶‹¦Ps¾ésơ±à ´ÄóÙ=OĂ¼̀fG å(̣ù@x¤wDz,œĂöi%¥ßÏg"W’]̀™ÙK®ÚÚÈ#ØdÜ4Îm›‘÷ 0Ơ­&URö́FÄ÷Å¿!êôiÍz!Û¦èRÆLµ[£ #á¸è:˜ÖW|9£­øÖëó—÷[wưéL°EqÖ ^ËN[.Xù¢aûqÓ ±g¶P]¶XöIÆ;L/Ń©J»Œˆ/7töÑ{6>“ _nuAüZ3™œ(5L®8ë³ê…ƒ25“ÈrăhƒÎËưÙÛÛƠh¦e¨9?_̉*,/•äè4¼æTÂź¢Gư4rặ1o¿|•3ƠG‚ŸÇ%ù…Éß(ù¦|uỤ̈]“S˜çbḅÜö¬·ÎB³̉˜÷¾Ă-ílÙyXêPÉÜÏ{xíÓÙpƒÇ«úÊ}£̃NNƯ^§é₫₫₫‚XÿR¹}K¼ PßÁ+¯)@Üæ.eơƯÉ5ăy gS*ŸA¢áȤÜ4‰oF‰ơÉ‹?J”Kʽ¢Ç\7â…—øñ¼vƯ²(Éü¥Đ©DU\&_ÏÓd}wï‹Úm™{®½*K̉ḅmëÆ—¶̀§¨ÁçQCgDY;ŸöQOq̣2ẴƠ2âÍ!Ønsÿ±¬˜̃¡)÷\§ö²¬lª½J~jc¸7L«}Z‘2F@I´0˜2y•é́b­~₫¡—$YIy9üQ‹”“Vú¤Ø`Ía>.’.‚ ½Ṕ‰P“¯Êåre¹>5‹ùw J̀$1NĂX½Ä™paĐ̃Â7Œ8{¼K0̃>áwhƒ@¼KBuûĐk£=¶sd]₫8Œ­RI¸6´ÑZ£&z*ÔaÔÍ©FU–%„ŒT=k‰Đô‰Ø“¶ÉÖ„œ+7TZÂ8Íß›öÑ£÷₫8zƠÏ‘“³m¼3Q‰µ—wkï¤Gù”dÆ—ªKâvµªC¢~ÆGv§ê$,49öv×Ư?2– ‚¡Ü₫•¶jøou`¡â¯„#¦”ÀM-w#ư2ÿṂJȤ¢k“'®¸9s<)ˆ ö¸ ¾Y_₫?¬°~ÔơôË”Ux”Ì$.^ïW§øBT̉:¤"‘ r)₫ÊjF&ˆ•WziW₫u>TÇô|*¿µ@0<Đç˜H1Ṇ̃$£±¸GQI[Äïz¾>ROµ•¶ø&æ="£Đ`lb/ĆǺá}—©ê1ûㆄj$+#²+U·H¾£ KkĐư^3₫c·³É¹üĐƯ©/LwÖ4w¾–¶ß2ÔRqXR•«?‹/‡ù¶.„4SyƠE“æ gwp̃J»&×µMq|5 ›½̉ÔÙûqB°h́«Ñaûµ2Çùè E~U6®äľȪw‚¿\’Ö^vá2ô§S¾¹ «ÅçF u•#’“´Æ4f³U{ŒR#éß!N¾…©Éè˜ YÖ.~=8¦å²jÀh+~$Iui’aĐ¼sđ;±«ÿúoÁ>úܧ¬Môq¼‡‹XÔø&ƒơă²í#r¸ƠNÎÖB̀r‚₫ÄI»2p/¼>±züƒ;Ơ'8̣¸ È#”â™Å̀ưƠçSV—ÉAÄJ¼L›vëă´HV„‹Đ´eü+Å„ °”>₫Ùp«¸yb#¶„é¢sæ€‘Ïæô›vL«â‚M«/”™~‘E˜|Ø‘‘Ÿ³˜J₫äÂk@]ẹ́Ă}„:é~z'ÿ9ẹ́>äú£I‰¶ftm‡hÓ̉²ßˆ 'D5÷6|XêøÔ”tøI>]µ˜̉•ˆ 5à‚i\7ć€̣=¼è‚‚a„…'*Pe\³»Åßd >çxϪ»ÛO͘=[¦q*7²Áú_fj’€¿­VyøË£ÿ FÖI(ƒ§xFăis¥ĂMŸ—‰QG9R7R¡Ph‚¹i(¢Da¡’à϶¥A{#ûîrÇ+¶^ÄÍyBLëfxâ½ûôĐÉ-~pGơ’́s„‘¬<‚€m§×äºv”û×.XƼ&Cb̉"ÿ@•Y_\₫x2ÓK¶Đ~Q₫X¥p6]¡Ëiådp¥:ZMï7í M6ºQƠăùZV꽪Ú@F SÀ‘O׌}¨‘#,¹~_„`ø§û$#đH0{êôç7ûYL(Ÿ…ÀGø9¢É'a9”eÍÄKƠö¡û}†ôlÛLZB.n&:ôi)Iûá̃úaÿ§;[¯Gư;' >ư¢;mPÿưÏ}!¤ç½9îy–®}»$;B5…àBªÁzµ€NÂCƠĂc{Ç4†«.¡V)Dl€\ê|#=ư{œäËŸz¡T 5¢ÙœÓùnÊ₫e¯bwĂ…Z™núˆ̉íS‚¹ñ¹6CH;ú©;‹ M<̃¾3Kă´Ư\»ñ…i>ku¿Àà́¹éË̉LëÄè,t& §EZ&â ä2Ÿøˆu.fđVï¦Kë•§¶„ïü´“gÉF9y†¥”½Á“›₫„/Nëuôlí^<¡÷‚íƒ%b 7Zæ í±ñH"ˆ:Nÿ󡬼,ØO ˜µË„Az©]s‡¥—¬mÑŒŸHíÿàÁæí®+”$ªqưæ¡M¡Ê´X$//ÂxUsmJbE~@%®W_Ú>_èØJmß¹NÔ₫”Ké?E»‰ÄˆHØp4_øs‚fÄ º»¡Ó<=}₫₫››©hä‘x­Ñouƒ̣ÉSÈqÙç‡Àg=hœñƯ,ô yñe¾#))ÂÂ_Ê–̀øW³ÈU wj!F+ŒÖĐ·ơ©%HRç1„k1ǽ`‚Ñ ôëë_œ’9!¶É` Bóy³S₫SÜ4ÂGû´O¡e„GÜ7₫”Ư=2ÙTøaBG2æÔÅM+é~ ±xø¾¤ƒ̣Ẻ¬uæ¯107L¹‘NjѠµÀiÙº2‹(d©úƒ̣ˆç~_7¾À+ƒóƒ̃e÷½§<³{;(§Å(üï1δú•öHû¤Î̀n‡íª0&j¥Ê ă<ˆ ¼̀îÚ¹*‘÷Æ ` ½€nÊêé¸l J°?¤&Fä8G·{}+ûÇ ^1È>Î&¸ß!L·&ÎÉ₫!01<3§ëE¨´/9¤“^ñ³ưû·»)ơ $å₫- å$ƯûCîƠ$ửn¤ÿÔ:̀[‡QQLÙ%µú¥FBZ>ºg̃qNYCÙ€`“dbĺ ¿;ï£"ø—ạ̊ÿVbYIg­gJ¿ˆEŒÜ@8íăªÑƯaÚƯză²-Ÿ–©ao‰9MÁf×R©x¾µÜÎä#fBf3ÿ®×ó~tăèiÏ; äÓè&ƒ$bµåâẸ̀Óg‡(©bĐôĤñ)uÄđ(IsÆøä »Iá"£!ô·J7lƠgµÍDy·¢ endstream endobj 811 0 obj << /Length1 1644 /Length2 6402 /Length3 0 /Length 7242 /Filter /FlateDecode >> stream xÚ­Tu\”m—¥‘.)º»;$Á¡Cz`bf†n)‘.iéP@Zé–V‘¤cGßư¾oïî₫³ûươ<÷¹îs¸Î}8YơU!{¨&‘€`îö†wBVWĐêä ÀØ%‰89`4 W£¡r3( uˆ‰Deee‰8÷H_̀É à114ăåçø—å÷€½ï?Œ§̀ àÂüxAƯHw(¡ø?;A¡´3àsƒîëé?̉ix´@&-(»ô=íƯ`]˜îå8"P·¿û]‡†KƠx ¡0ŒÔÇü P”;̀Ăó€yœP`8Ó4ƒ;¸yB~'€±;"₫$„D!07Ü1†Láöp@Áh&ª¾ºæ_y¢Áèß±=`€pÄÜ„ <—ôĂĐ`P4÷ ¡>èß±́¡̀éöÅÄÆ!Q°?ixzÀàNÿÊ@€‚:Q7¨‡†Ăư»;ÿªđ_ª#‘n¾¼nư3Úêæ(D$*†‰é€ÆÄv‚Á‰„Ï6ÜùËñD₫ó‚¢₫4ˆç÷̀đb’Cp7_êH$ B 1!<ÿ7•…₫}"ÿ$₫·üo‘÷ÿ'îß5ú/øÿûÿN­ééæ»cà¯À,0€Ù3]ÀïEăFư7°;̀Í÷óúûm3è_é₫/dÚh0¦-ªp'Œ4‚²B2"²0M˜¢C;8Án˜¾ư±›À!P” Åèû§µAQ‘¿aÆÎ0Wøo!$ÿ‚ pÈß«ÀHö§aƯ@ í‡üÿ}É ¹a†ÍVTJú/}̀X }‘PÀÆ3{ˆ€üóđ›PM áđ•’Ɉb^#&5Y1‰Àÿ!ø"Ñ‚Ñ(˜ÀRDHDDCúû+̣;ö? ë¿ÑhÀ߃d„Ă!˜Ùû§á7́à‰Ba$ÿ³0ơÿăüç@¡>P¢O3ù'.éYèºÜ̃auË÷¢·{#%ơÆ…¯BªÁéQK²åv—ƠB £r×;Ó[È«oøÖú;iƯ¸;R¡?̣™Ùy»^Q|åj‘æ_ ¶)!ÉØ6‹ơß›̉]ı1][60´)¾ÄcmǴđ†°{½ ¡æ8F’9¤Ơ%Đ´’7`QÖlms%}?9æîèëíéø‰Ûơ‘ÿe!§<˜.(e‹5ík‡:ªw¸Æ=÷’ö¨˜În4«¢H2ñöc¼˜ñdáø¿D%±+~ÏéF{UDeÆ>AÇûÇÓHâx±ÂJ,ƒ÷ÇŒØÔ¶ÎhoÏI}̃©S’KwÍ“‡¯7Ä̀h¥³J.\S˜̣¨»§²,"!@Ṣ ƒG¦1c̉µ ÊœJ¤1*5!¯“—UâlZĐ÷Û±*Ó?Ôælë ö*Ân Ɖ®{?;z¬ ¢¢̣È%’o;öÿܰL"^yEáVê×Zµ×#.½Ÿpñ•ÓßÄ·QT{ëüXå?§JüễÀ"«Ëyp˜bÓØaÙÖ®!F2©l7¶ñ¾A§x™À·¾÷°}«T‡P)”$‘b±}E:e_ƯÓĐ `óƯj©œ1ûZjVÇ3©•dyæ,Àñí ——²I~ê I¤Ï3W̉ÉøÊØ¿l…DÜ6T™Öä[,bîZ:Öæ?Óp¿•`?·¬{92ÿâ–iđ­ärïù¼fd 'r•0ÀË+kúy^n% ûjÛ½é«'oüS°é},²BÖg çÇ¼đ²¿¤>w.´wíw¨b6KÅÁ¦2Qj3xó€±̀'×ËÇØuáX7Û`Ơå4‹•× àï¨Ô‚°—›÷ëtsÔ+%ƯÉƯC#Km#|j=Lɽ|‘Ԣ¿^é‹«bé̃Ê™“«“ªîV²Qá>‡aC ïÚ>y¹b ‚w ’ú„ÓT½{üBO0¯̣LưÛ ¸¸‡-ÜF+±«ê{đÅI©Ë…ŸPiÇ L.r³<Ơ•¯WªÄeÄY¿ÜÔ°:dlZS_z°R–;i1jæ½O:™Ù™nóÀJFˆöµ üƒ¼,b"Ê1o¼@89ç´¹· ư>ü«ú•xNáÖÈnhưÆäIg©„²Bä2>´=µ́ö]}³¬[£×`«ø6pIÇ/!ó*Z¬ûE —%Z¤ÅüÏ—¸È^ÿ*óC×$̣Ươå­pY,̀DH”'U™ˆJKɿڟw¥rpî­µơ†y›—±ÓCœFôËüV`næí[Ñ.Lăô s1âă5’ü’nIéAŸÀ̉€1₫ƠZHoañSvBÊƯ~c!’g¤=j² ´O£qyKW\fÈÙ ^ÿŒí1§Ơ7hXy¸`đÎpᇮ• +å·Ÿ—÷7ù;đ4F/Q•úR¤ÍØ“®[‹£ï Ån&jÅe%‘;hY¶Ä~¬Us®ü8óaâ¸O_¥xty·•¶9J£eU¼äc–·&#ï:(ÖÁ…ج|Ám-«Ñx~1T2U+4èä̀9X\û¶%aÁiûѵpnŒơ(+7̃/x{5`ˆQ0—™€ü ơKÔ- ©½ÏjßwŒ“=QO÷+©˜ÙÍMDï÷@ă$ñ¸™¹~ç½oyR°ăgF*Ég Dä&F ‡;~¥Ä|Lö5jó±H·ĂWb2n-ͬêr¥L-ó90–“ê2[9BU$-m—OŸËt÷£®v‡a¼"êŸ{›÷ßÜ¡ßî¯Ê ·\Í9V¾.bïă³¯*}á9™́ĂÓ[æd™Đb1Öh’ïêv > t#§GµF²„|p©”¤8Í(%zqđá-ß̉»éÜ’˜̉µ)øpÑÀªån72Q÷ç4¥’} ¡‡7g|èàơ2zmxJ*fÏÄ…‡™Ö]#˜`ƠÿÅW›Fk÷̀øÑ}VC3&Å~ïgw|đ/Ơ \Áe–ØÅû_Tx>ï¶j¾ ‰Vö=dǹÿ‘jf»Y‚‡(ê`ÙeAbúFk^±×¶ơC|IN{̃A·-Ùd:$]wù4ÉU¹_ñÛí'±ÉAB@ëæơ¨̣½¥Æ,c„á<,x0)ƯôV\iRj‡L· §d À{uI H€.̣̃å-Öó%ơ"ˆºf_²zAZÀ G!³å‚?*—–í?v‹¦µ@ø#¸ơ…D+ff̣í¸›x”K j›̃¿ÜâóteÿĂXAγ7ç—¥Ơ“i»$­¤,#”Ùä"›Xú“]̀Óơ'%Dnî²åÄ  g8qßn¹d—Ôl 2zƯ £¦Ï΄Êw¦ưg[7›d_t›‘ï2?êÁS˦ Ur²²âù’ÁÁ.²ùµj2ê‹ñĂHJëLạ̊ư'!3Ͷ ( ÂD#£đ•H+[úK̃öü4¿©>ÿÍÛb†µI AR}÷ç•k‹ÎÀiÔ&r±ĐO»‚·€<‡!Ök&ƒ…ÙzeÔ­̀.ä[½J… k–¯_´Óg—o!|¢”N<9|Êé°IK ªu=“È ¡çăÚ΃ÿ4K‰éÄ5VÉœFlĐÆîPÛU~X;Ëel3 ÓƯûù5Àăư¼°$Oó—ø‹:{B̉›‡AÚ•®̀M=²€ư0³)²h²¾U›ÈÏ}v ¨7dJÏpg•çT³K¤|WaO˜Ổ€íKñ ½w‹Ûàè o ’l ONßO/´jœơ÷cĂê¾GÁ0½6¾9Æă„ƒUŸ¶p³FhèYß ñÑƯQ8]’y2{³ÚWÊÅ{Xó׿ §6¯‡¢ư5gzdr˜)|a5̉$$_Â^¤Î×́¯»_f_́zlÏ’,KÜ?1ư>i@"¢ød ̃̀8 ÁI^Öêûxü94˜ƠR\WTü ‘ËÆú]@EápÈ¥qæÄ̉“G1;Äû©¯SéÙ¤Ơ©é|Ư¾ê†™ĂK•ÎÛ¤"R3ÎẲé`¡ÂדÓẹתI±z$8øûW×À•›Çv¸ư;,V~gK§ö²²¯Ij½?xj̃]‡E½ •,hz[ÓÄ}HZ¾ÿà͍·z×éèEÙ¨F‚Dïå’^Æư?.†Ô ?æx3 ~±J‰0<&>2jÍ?F Đ¥́ç ;iù‡56V{̉Ú P1•°q¹P̣Bm€A[j®‚àˆ™€·ÂÂ}HfÉ1¿qĂÁ,}”sdjx÷EàAªˆX²ŸÁbỹDÅb’¬OGVZ“%fÂøûđµ ­å‰aâY_6Ç1jFL¤_”·°èOœ.Ô6¨ ₫K{WŸ+‡̃ysá,øD°L“³AÏ©ØùKSí[În_E󒈹À;Ö²̉ĂŸ3̃k„5ĐGKPc.r„€aŒ£gËFê¾Í2V‚ØRf§Â O1_°iŒR„Î9x]Ẹ̈bÓ__K{‘0²ö×vn¹̣½¾fÚPÀÉ%Óθ4 ˜₫N”­~6¸/âƯ à7–chÚ@U¥pÁ¾k•̀Fë—^éBS닌TDÚk¥VâÇ¥-iè¼,‹²ô÷r̃{°Ÿø À×Oïră¥yw³‡œ*̃÷ûî*[îAH¦™ §A¢ê B¢TÙy¬†ÇI/ó’Ăƒ®F;UúMø'‡gL³ŸØˆí×ǹ¿¦py™èÑ&{ÏÔx $˜Äçp‡9\asp‘éĐÈ&ƒ¾́t74Mi:̉w_Öb’ô9OÙl;Å#«§-írƯ[[vRưêåḅË‚ƒ;Ó¬\x™ïØE3e´`÷hâ™cÇÙWOˆV́Ê YAvÅæơĂN$v5s“S Ợç﮽• - §óÎ́‚8çE¥¬çàÑwÄlSÙƠ:'Ê&—qósM Åb‚áˆ5¡»,‚øÁ¼OåAsGA²åññagNXs•"-8ÜíÑS!ïâBtyV…ë;~j´}~̣àZµùˆº²£¾ưr‚F˜pL¯&0GȬ•e²I¹—n=¸·[̉@}ƒz¤Wà5₫láº8é̃…¨Ü>XĐ̃ªú‰£µƠ /náŒ̃x9ÚA’›]G̀¾Iˆ”É*—÷¡4's¢ˆnIz˜̀q›üUi‘uăÁT¨ ¾xZVîÆOÑ;¯îôÜñằ<Ö ưTŸŒü”¡Đ'×ÖªfÿÊƯéåÔ\ptƯä CTUïă½G3/grhNiW±²5«ư] [êpí6¦)Y¥Ûák"«bùY?ÉÊe˜Ư3%¸$cS< Kv‘ăª)ÔkM±g̃x¡ê;è·`-sÈ4œ(x\½Ă½P{L8{Üí:BÏ«³y(¢¡•V?£IPơ®Úox¨ ¾ƯVEâ~ ̃—7L#Bx.Ô½ün-0&×¢r|æ̉́iíc!¹̃‘uH!9k®6®Ä-4¥¦ôY,„™4shụ̀KPÀ­Y#à7T½uY½©DEF²́¯ÆG> ] bZ¼˜ºFnàø®̣;µ~©Ú›ăƠơ›–q'*ù•-,‹ï,” OÝ4’¸¿ÅîÏ€ö‹‘ÆÙ_è¸VkJjŸÍRááúĉøE;xP¹ò:.ðPk}ʻ٫Z₫Q–O£­ÄZơ•QœđŒ.í§ê&=¿;«?œØe¢©œ×ÍC¹˜Iöö{ÈÖåË‚ Akư§É‘R̃}/_ƒ²üPÜpºfÏï>_­2\°u3b4ưF”=Â%êÄ[RÏ:˜ơt)?´-Uăa+µ)_uá±´µÓƯ¤Ü¾̣úŒ<´eÿY$Ræ8…c£[‹8¸pe0xƠékö=b•`ªlÈHÙ&u8OuDÿ̀s©'¾Œ§€…¨­cŒ£Ah>ôá*èØ"₫,“G'D=%ÊúéHQ 'ö4Ó́YÓd´̣₫¨†ÙÊrB‰ä*èÏ»¼rùs™I,Åø¡çÙ)%à¯Û¹Ÿ4N³¬éÜèS‘#I×‹ĐŸiË]“}%¤w•2&ÇJ4Mv–QÏĂ¯¬\ª-Klp:³³å̉jÓ»'⌋Åñ[ånpë,'>6'ế?Ăe¨ºá̃̃`́êđ‚ƠååGâû̀ăË™‹ymT{B^ă$™QІ„mèÓđ%çå}nMk¨+S§5¦˜îæú®VpeŸpÚ“}NĐ}y¯è5Â% «3ÔD‰ơ>¸îMĐgú–áưôí3Ơ2Qr_'´»¥œƠ{ùñ›:Ó„àZ)ù̀ÙI‚ú:î°U˱äưÆFêRu¸ÖW*ig ®˜è/&<}×Ë™JºÓ=æ«6 ¤éø“vó¶^×z ½`ëO‹x¼ă²¥wû…­¦>“;îfiÙ4=È¡§F® t—d-s„Úº‚,qˆOoN#Núéoi§_wQ#Ä.xg^éO sú iăÊ Ú?›:©áeü•4sÁ¨Öúơà@µœ+Ø? pm`xútơM×ó•è`*ÖR~́ôJ$t&ª¾¾CÿÍcKU‹·|Ru`ưW{wL—Á¦́°“m0¯ˆ~=áÚ>|Q³ä¯ĐY·!„OĂ}ílQøÎ3œ¿0÷R}*̀U“Fú„hŒ¥µfæŸ)*A„Uß{Je…‹³™¸¨>̃j./åœOêZh!uô¾éÏæn³ù`¬ư#²Đ˜q-Ä̉º»Ăs4ø#—¦?Ăhû¸u±¸ØƯÊxĐ¯îî›!·˜ín®U‘ù!ºæÊÚº!6WßqÇ)×w×@:ShA¿®Á KĐ̃¤ª€IˆÈÁ%‹ 8uæÿ\á¯@«…OêÛ1¦²Z¬@â"R¿Ó[¦Ö¿ M Œ‹^‹¸ôßœ°áS7†Á‹¼í+¸'‘ª+O˜z´¥!@ûú’G“ÑÛ_!ZE ÂÅd$Ç£3½üÉ’b̀=w*đ7vNd‹ÎÍÈ+µÆá3R*©¾÷AI6D"âÚRï‡L§êï-­bE4r̃r˯÷ß3„a1ßiÓ½¡p_rÊ—mµ«„·–(‹†ºHºl×Á&Ú…̀\ô©Ó^Êe:©5ùT§GQ¶X®›ZÛ|¯­üyôë?ˆ· endstream endobj 813 0 obj << /Length1 1647 /Length2 6319 /Length3 0 /Length 7155 /Filter /FlateDecode >> stream xÚ­TuXÔm—¦S@j(‘¡‘n$¤»c”˜Ñ™¡SéVBin)Ii)é”vôƯïûözw÷ŸƯï™ë÷œûœûœóÜç9́̀úF| p;°*ÜÅ'Ä/(Ô…:Û¹# áκpIm>C°“»ÊDcbD́́J°- wQ¶E¥€&` 2Ø(, ’””$b*Á]½P' Èelḥ€‡‡÷_–ß.@;ï èH$ÔÉÈ₫đĂà®Î`âÿhQ0Đ •ôôÍ4tƠ€\jºÆ@5° nBßƯµjCíÁ.Hđ #„ưuÚĂ] ¿[C̣£¹@[ ̉lE‡½́Á®¿!^ +á E"Ñß@(è„°uA¡ïB]́aî¿ @Ûá rEÀÑÎh M¦G¢ö¨+ ˆÎª¯¬úW(ˆ-êwn$ áhO¸½ûï–₫`h4²…º (°êw.;0Đt…Ùz£s£É\Đ?e¸#¡.Nÿª€ˆ;Ù"``$Mƒæ₫};ÿêø_º·uu…yÿ‰†ÿñúg P sä'Fç´G¡s;A]ˆ~Ï‹†‹#($ø—ƯÁƯơ˜ñ炸~Ï̀t¶p˜7Đ́H$  G¡S¹₫o*óÿûD₫7Hüoøß"ïÿOÜ¿kô_ñÿ÷=ÿZƠÓµuFÀ_{ˆ^4¶.@ô®j/˜-ø{á@íÿ[¨­3æư¿ÿƯÛüWƠÿÉùwø¯ .Nh…ø„ÄøÅ₫2C‘ªP/°ƒ>e:ÚÂĐ—÷ÇńâFÀ .`´Èî$(ø7 Ú?sù­†Ø_ØÅáï= uûÓ€º’‘’)Ïÿ²mÿ8룧̣vÿ3“‰ÜះßTp/ /Ÿ¸$OXBưÑÏQRXÔÿHû‡Hè_g[ê´ä¢ÿÿñû×éÉßhT\́á¿çÈeë‽~ĂöîZñ?ÛƯù?Î́¶'‚ÛK‡>}“ª ÉîT¶èlÂî s}W *È *ƒ·¾‰ü&Yjó«<Œ¿fXê¦Á{rÇơzM“{½¯ăl{ ̃ϽçÏú #|£I‚g=XÀêIê®ÉK߃ í%sqÁÇë˃†Voá17‰ αzäQ±¹’اTÅQ7ß­Á ¨ÈßÙåHÜ:?ắîïíùÔv„Û±ÆÀ“GÈ.mK¼Ăœ„̣¶AœVÛßà^zH¸{’øR¦^»³>wayWªôùr!ÄƠôî$dØR1Y= ©ô9è9…(=bFÜ û•&á÷\µ‚5Ö>üøđîZ§ô2Á{É‹<Æi-¦A?ªg^“ø© p‰¤íixÛæ˜ØB>J«~å2œcL'6:St7¨Û ¤§JÈÍœF öä¶Å0•WiuTº¨pÆo]%àåơ/<·Ôßúéô‚†DÈa¡́>ñÙ—Û,g{EĂ2#GÙʹ<Á·¥Og_ûüª‚H¨ RµRæR~ñ·êÖxé×{$p₫Q¨®,OÙî¤mSi±…¶8ë«øhØq¬ưÄ,nù«dƒÓơm“Ø˜Ă²·Ë„w'–ñ¾*£§Ú%©²oñÓ́(ƠËÚ•VÓĐTL‡|…h—ÜsàÖI¡{‰2 °ék$Vo˜ÀbI_ĐG]°øHK-ºDdæ;Äx7¥|-+E˜ÇPAÛf`Gª¡»*cb1ï†iGµœỊ›øEVYQ$Ë~ÊLăm‹€!ŸTç‰çëû´éw2âVM ‘Ûæ_06x&k·T[N;81_€̃E;÷*ww”µøŸºNó«̃ ̣>Ú*¤đÖñ$‘¤Çàú5P¢×=,{0BQk4óË̀4:\×á]•9<\È®3-÷0ºA3 àFĂ³“Ëijîü¡¦B©Í‹©–^‡-¾-oB’€ÿåyes¨¤T±#aù}è^ªJ́n2fƒ¶~Đ¢̣₫Àà¾nX® à“Ạ̀ÿúÆ̃é°¦«1cNa»3aSÙY>—oàœC¶7¤æöK˜¸J˜Ôø’.1V[Âư8<Çü.ùÈéZï‰Qs¥FGTDÑóKˆœ‘άƯ™!u·oL|Èóåù»BÈUÂü X—rÑ!‘ZWc¾íÆèg!̃WqÓ?VưÂUGƒ®¢ˆ¶ZYô1µ”K7Ó"gY2î‹3:Ûwlàñ³>¿œÛ|W¥„]Ưߌ™BèT:ˆ¹¦Ä³¡̣QäƠÈNK§I‰̉ÿÎ0½F´ơ3₫smºZïÊü—\äD'O¡Lí¢ñÚµ»2Χúƒƒ],Êöq,ç 9ñ>‡œç”ˆíïYs‡Öèâध’G’Ê=ɾÓÔ°µơ$´—R¬Ñt¹úÄ₫m‘U{9a•tjT)YÜ颱ÏQó8'^È€ñ§lÎ̉µ¥jÆ£ë2ơ£#!ÙFÑ¥HÆư¹ÍH%ALÓWqíïƯ“Á¹´¥*Q[Ó„¢[¯đm‰sÈư«¤v Ûês´>‘Ü´Éc3…ó_>̀kÙ¶±äŸZKÓ”©ë÷\Oµ6w´ 70Pöµa3–iæåÆG²L ZẒQ –§x›Pg¡¡8둾7ÓøÆRŸ6%ÂmW”F3+ÏW˜(/•|ɼ|®Óá‰14!äèÂUï-h™ƠzÀY×®¢hŸHÉáăùDzH/,z-TÅßUXÓÆ|”P|{.—û̃`¤5‰—ẹ́c“ŸĂè ¯uxûzü3iÓƠ˜ €‚ 3̃Æ.±ǹé9¶GĐĐă{_º hEr®ûó¢ĂÜÿ`z¥¤¦¸iQÊêMm…¯x̉ £r< 5–H˜º”¦Á((f̀Ür"²IÏF0&†ùtYớ*~¹C’¾/ñ(Ê¡ßVïp^²̀]G¤Å-5P=¤»[” hÝŠή}ºä¹¨N̉Û[<ÛÎ35ˆÚø¸3Üù•²h´îiNW^S₫Ñ₫¶#(¹6ỡ´kà́µnù*Y\`ư%¿r@‘‹¥) ’ơN¤& »uïQ™~têÇé”}Ơ( ëÈÇy±́ê8ưđ§>S)àL2­tßo­L¨/™w/‰Uö%€÷JÅ6Ư裰Đaeç»—µXOR“@Œéü#…¨'6ÏZQ|C=)¸­IŸvctơC0Ù`â-yCVn÷×ơY7&]ùÈ)ƠñÅ ˆø›mÔ¬ÆOẲ‚»¢Pó‡ B}eæK'J%Ư<–<6ëçLJS©AÉB]¢)kj)L£#‰«ç:Ñ~¼^ụ̈ÇŒLï81}&iAXu%\›MRFmJ¾`éôLSg.‘‹ïØyï{Å«ê}€qjbÙ́Ă­€—FUĐj°Åñ±„O»Kä4P[o‹Iø KŸÛÈ_§éå*$SntQî4hª,×ÖM©K°îÓ\x'­ºÊTqqê§aă¸Z¯[@́™K½Üs³TF$˜É)¬ >V÷_¬Ä¾es…¤§+̀'¶”ưT¶yMæ(uv[« ̣6ûg5TSS½èÚOƯk‹…Ù`J?<ͰÖQ…°…%»sÈhó•ÅZö¡|ÇøíYˆsêÅZL-Jµ f¢kđtËtJ!ơw0¹Ÿ/̣%hæ£|}´“c÷ Né<’Œ1OxªCT@N_h<½ít+™Ç_nfIM;2?´‹t0x½÷’0É/ÈJ̉.‚ÅÜ‚óŸØ/5ˆ¾ÈuĂ¯ñăg§ÀE8@97*ëÑƯq•mI^SnAD1°‹Ùb…my¾×¥qÓ¶ŒưT×nƠIæ<ç7«„n1cá¦7I—?ă2×®ÀơˆÚä[ô$#yGœvÜß{²S ‘”¤5½ÿDg~ôVË„\›äíXÅå­ë }¤¢&‰*µxè¥]_ô1ưÏàJ¶f2)‹=Æ…fî/µ=CÆ5œµl4ôåÎuđg=Ǜ«g|‹˜HùcsÚXD˜áù³¼ ¸¡KïÜ%;cà«\»(lt—#¨/®"G³×Æ~µW,à•”x+Nï•›- Ö¨&𕦆?úêMv̉Æ+ĂĂƯÿh¦qÎóv-Cbg‹‚|0¨-lXre­tP|ê©›x ĂÙkư8Qơ=ODDđ˜À«W¼E—³¨¶Ë–X–¹€Ÿµ«yq!2ʉĐ̉́ZpÚ9ơ8A_êàơ&%,%§»b̉hżg§̉éeSÆN‰Pôk»´Ërƒ[ü~Ç:LZl‘½! ¹myºr }hÊ₫a†–ydüuhà˜’£ưˇsHüˆø¾9,›lÓxáƯ₫g2$wü‘´ÛÎ v!kÓ_“¼oD=Ø!Ó=UÁM?¾VĐ̣:íăÖ îÇ%ç§.÷đâ”ÔÄ=›ék±ŸQœ 3z|°ả"?)°ÉTC“ಹ˗’W­È’Ê~.¶íçÄkr¤5z”=7&ñÓÓp€ö'UÀ!÷KÜ r̉b_s¦=Ă9læ¨ &}Ëge„Û‹¸E+ä9& ¤¨ƯçÖ-ËóĐ{²æÎ³MR&»́Uç ´q2VYæb“JÅ̃Ú™¡p“N*§ăÈêq黋LxIbêUY“Y´m†ƠèɳLÁ½Êy~NZŒ9ê>ˆ„Ï@©&Åe¥-̉'  ›•y§¶S ̀'î9mᇟĐês÷ž¼£³HŸ“®3J©TÁp—9ÉHÅØr$sªM`ÊܦœË2yæ³ưAÏ"%#eÍ“/[₫yóÛÛ½} ß: ûÎQ½ÓîÙ…½F땼®~¸_~UR1¹âƯv çN¢¦´%«sÍ.‚½ÏÛ^á…)Á±ùQŬ<ĂûêÇè?¯¤´g´9î#¡¦n§;đ•[vÖMPL0‹ŸCê¼®ọ́‹¾Đh’¦l3Æ5¡ƯÏ­9É#àpNÏQṢx oÅpÍ}› +öM»™ăjÏư[‚°À˜ä{åû¬Ô÷¥¼¢pÏÈ…÷œAM¸Tj£i:XESưÖ&T_«Æ,K'›¼HDTnÍ>ߦ×#6&Øè²-æ6¶mê>>0Ëk ©ñSÖkø4s¥z`œVweá6v9bÖ•£ª¼Üñơ¶Ógˤ½ƒ}!Ÿ³8{R̉ܯߔÁŸ©Ï̀Ü}ÇdbÎ@Ơ<˜<W¯CơÑÈ́Üäăóe¼Ä^á8< n»}qH—qÍ*qW?ú½¸C.íB¼MÊ0J¹FVƠb3`ûC+Ef±bá•*r„Ô›½]àă‚CøÍtYk4ÈP®°IcªĐ@#˃ƒØM"SA3¶ƒ _]c¾ï®¨Kh ùM©·jèê_#ûl%Ÿ³ú•|ûVÎaMg·•*ÀgÍ€ÎË(Ơ:›ºáGE²'#ư¶»÷‚IơÅçRn*Cº¹=˼P È;Ó± – SP=à£̃=Ø*‹O²DÙÉ(VÊ ,¶m‡à¡:áXྠ çgÚ^µp̉‡,:ªĂ@pB0»¾IA‹æĂ@ W÷,2±³LPƠḳü®/ 6äæ’¦•k/Êv) ú2Ăh?fO¶j̉û ! —TN¯M5È,DzQÂÑ>ÓÜÂlM¡€XxÿɧϺBÈ9ö‰ç£´0¾Úé&±º2‚óï@Ùt§e„Ôn÷ׇ’„H‡‡k”¤ÅØëüôŒøŒËOxœăè£KüÀnƯíÍÍ•hv’ơQ®$aÉå ¯h~\äÇ«vư¢§ *”¶ÔrAŸWF Ï›’°ü -‚ ̃|ÖÚX½ùʬ®âo§ˆƯœ*~Û[d’¾IQ q!ơôú́å ́8̀4VäÄÿđ)æoLц½ơtkí)½ñNFi…ïI«ßá̉ïÉ×s&=;Ơ‘`˜¸ÿiK4j>`Å*åäF³ëáœđ}b•Ä”I‡ŸFÈ?In¬ĐæÂ‘üưk~Kàư&üU£F3×U™ÍºfL;ÚW}˜»'ư¯0‡Æu Ÿ‘tÑ%ÑÅ©o÷Qx£JbD¹Ÿ5¯$èΙ̃ƒ^$aÏúç¿Ưœ …´æ³?Ÿđ~“ÏMæ@Ơöi­Ôxhr,Zu³äĂO÷{…Ú̉ăÀ©Sµ ÆVÏ ¢&•ĐW[D¿(å?±ö®¨qJà”[ừ-hˆà₫¡ZꕱO7/}‚)³Q}ƯÚx–=t¤KÎ[LS»#ûú"]ˆ@4§çKĐUÄÄÜcó—.†¾ç0₫5~³Åâă#Î0Ä|₫ûÙà$=%SgºÛ‚‡˜ưbV¥X¯đ¯½Œi§’—ë7]ă¦Åx£·L‡~Mxù~r̀,ÜÓߌéĂEO´Ü–£/˜¹É‰éX¦ïđé[{Mø)³œSĐ)¬0s‚iJD/ÿ >¹^©ƯJUïl‰ăÈ‹xk9.Hàû ß *~Ă3¹ḶüaÅ=:·ïö„ÍëàÂR ǰăœ.¶o]™ó{›ß°#…;®̀]TgêÄw²ăî]=‰M×¹IçT, ¥>¤‘xÎëñ‚Y爑0}âíWÁs7ÍỌ’î‡ÎRZV́û|8Ö́z%”ê—?œ«ü̃H?kœyơ´’_Ú6M©@Ơ@¬ÎÛPPܹL/ûh¢¢aư'*'đĂ)˜fä§‘Ă£=O„mǾU›âI0Ô´̃Æ̀¥=ú₫îöxLy₫™[r¨H¢xGWöir„ ÅHûéEÛ öª(¶B¢ÓĂ1-鉋ƠB[ƃsÚ»ơÚ;÷5qw$MåÍ#&¾Î}ë±»ûÈ»K£È’˜ĂªÑuï,)Ç}ÂÇÆb’øèÔ(û•,I‡5®h­=pT÷*ÇA&3èäPíéĆÖá ö×1 •e±îè:ôÙaÈ»â> ¦x̃fÜ›Đj& ü8₫øËi½K‰Ú¥ÖD…”ót7Ç#Åơóm‰YQi-¨˜7°u-§…(¡}ï<",l×± DXôPn^Sÿz¬êá™rÆĐÍ™‹Ö7ßlĂ•=«µe& Z2¹†²¿ Áá&PU´Ûv£ăóưÀF]|k¹ïó48{ØeŸ8×8 đ!xƒÏ P.íS›’uzª*ådÉ.}âWLºd›(ä|ăăûFQA­?¨ÀL–V¸óăl¿›}éñMKtê´îƯkäÈÊ,ï=iwƠ(̉'ÎT°nLíºx’s©uQù¢>‰° ïVVdZè'@äzæIÜøa¹ü»3;ÛÔ¾\çv1riù;mđ¥³ 7̉ ‰ṕ¦¶èQöĐưF?_I®ơÉöÊâhD ´«ÿ̉“ñF,"Q'&o¡Ô_ĐïÙ¿æ’ñ\‹@‡î₫EAÑ"]?I¼÷0—Â¥YÙ6c½,œ€Âp:è³Óa‚y"Ü¥¡TNX6˜T–y  ©ùư©èaê’î`̣´{/×±̀W!LÛ “yÿ&–ăW«Lrˆê]³öăª%˜O{¿1ߢŸĐé¶p*½X´Ö«à“ñÍñ„̀ÔÆ0JÛŒÚ& ¨I¬«\R:œôE‡>áûÊ3ûø–ulưÑTÊçMGX¤f¯ß²†)F—Siù_irI ¼U:k«ÇÍoÄ„VqüŒÔĂÇ| $jF!Èä6p¶ø¹egÙ…ó đ½ë‰€—Ÿ3C'oalÙ—è’e»M¼áS?ë ú_wP+ø{“Ă~áă>€å$S³i?e…+JHf.cŸÍ‡‚|ŒÙ?7嬥¸_Ø\‡Ôáß|×ÏÇ×I3Äè*±b,›È8Nò́kmpbÇcäw_'yˆuño¶©›¸ nPrDK&Ÿ`¼_h(”ÈÊÓaægûâB)ˆơT©QM³¢ƒĐ‹ö{S"ö$9¦Ơ„÷ËƠ—Á†Èưöÿ tu endstream endobj 815 0 obj << /Length 696 /Filter /FlateDecode >> stream xÚmTMoâ0½çWx•ÚÅ$ !Ù ‘8l[•jµWHL7IP‡₫ûơ¬V=Mß̀¼ñ s÷ëu;ÑU··ơÈÙ›=w—¾´“́÷îƯƯå]yil;<[[Ùj<=?±×¾+·v`÷Ù&ß´ơđàÈ›¶<^*;²~&ûQ·‚>́₫Ư₫”MS >Ù_êăP·̣{=éÇsæ@öd”ôÇöçºkŸ˜xäœ;`ƯVY×`Œs4½JaÓQÜ¡n«₫ª‡í¡.’Uu9\ßèY6î>¼ư<¶Ù´‡.Z.Ùô͇₫“4>DÓ—¾²}Ư~°û¯̉ÜÑör:-d0­V¬²WÑÍÿ¼k,›₫8ăó₫y²L̉»đºÊ®²çÓ®´ư®ư°Ñ’ó[Å*²mơíLrŸ²?ŒÜÔqù¥ă• â5F8@ ˆ=@đ)&°  È8Ô¹€ÂÅRx u€Dº\j2H—†ª¡ĐVÁ¹0CzL]ø Âb°ct‘I ©g$`htÑ‹0œÆ\F„áŒ0ä†sê‡á jd< —Iê6œ»ơñzgóñºË»₫ê W ¤qÈ’£+—Ÿ#ö•ñ̀ÇkÄ̃ .‰bªsré…¤áæÄç†bïmXú¾„Kß7ǵHß7Géû„û¾nb§>&jÊØµäuœ¯¼ú•ñ1ÜV™÷•âÜăâµÇ‰Ou$ƠŸqWèS/%1{\øxB!€§ÔK(hH©—TĐ–æƒ»J©Ïϯv×ÜëÁ=kü̉2ø¥UđKÏ‚_:~é$ø¥Óà—ÖÁ/¿Œ ~™Eđ+7¿èË¢/ ÿĺ¡Û̉(/}ïö -+ZXukoû́ÔE?Z„ăæÅÛKưqíƒÄ endstream endobj 816 0 obj << /Length 739 /Filter /FlateDecode >> stream xÚmUMoâ0¼çWx•ÚÅvHU„dçCâ°mUªƠ^!1ƯH ư÷ëñ#xÙö?ŸǵÁÜưx]OTƯmÍ$|ä́Íœºs_™Iöss îị̂®:L;<S›zœ==±×¾«Öf`÷Ù*_µÍđ`É«¶ÚŸk3²¾'ióÑ´‚}Øư»ù=©½à“í¹ÙM;áà¾7Ẵr¾›f¶Ænj̀-ùeúSÓµOLg~¼À8÷ă ăâ₫È)okà çA„8 ö$`I\èÎ×3`çAfă<ÈZ]ƒÂ!‹„ê xNkÇyă¹ăĐđ"œ7Á¿ _¥ă“§̀q âH`̣áö•‚nú¥¤k̀ÂđRONH=CpB:# =Ñ%8“ˆ88QA~¡!*ÉzÆœøĐäT?!~> étw©8éÄy*ás£¤Ï }nỒçFE>7*ö¹Q‰ÏR>7²¢ G]¼;~îó¤Û<©̣6OßæI‹¯ỵ̉ktèó¤g>O:̣ỷ±Ï“N|ôÜçI/|´̣ỷÚçIg>O:÷ỷ…Ï“.}2îó” Ÿ§Lú> stream xÚmUMoÛ:¼ëW°‡éÁ5?$R. ¤d9ôMđđ®Ää ˆeC¶ù÷³k›m‘CŒƠp¹;;†wŸ~>Î|¿3óE_ñ¸?O]œ5ß¶‡âî®Ưwç]Oßćc]=~?§}÷Oâ¾yhÆáô9%?ŒƯ۹׬“B|Æœ‚>â₫)₫;ëvÇw%gÏçáí4Œ3‰ä§áô–’>\ ‚‚6ư§ă°¿ ơEJ™€ơØ7ûÆ8ó 1¿’{Æ~ºđÏ`W(-ú¡;]¾è·Û%=°ùñưx»‡ñe_,—b₫+-OÓ;qü\̀L}œ†ñUÜÿI--=‡·B«•èăKª˜æÿ¾ƯE1ÿpÆ[ÎÓû! Mßyuû>Û.NÛñ5K)Wb¹Ù¬8ö­iÇ[_®¹uÊ•MúÑzQ­¥̉)V†€Ú(TØ€àx¿à̃¢ jy‹°°!ÀĐÔ•µZÔÀ2àP="¦ZdÔ0\ĂƒG©R\¡·”).–2*ÎШa!„U¼Ä,†³ÔÛHđ° `+jĐĂ.¸5Nα@èâ°èĐVK-àxŸ%ô˜Ü3% A°YÓ€z¡ÎÔ>kP#¬³¦ơ™5m0W£o¦Ă¾j­®§Üư·.†ĐZ¡T$X/©)n)æ#W—„o(æ“oÀRZ̃ $K¢p4’Z¶-bâ\­1¦Ü°Jä æP"Gñ‘XÔQ¬‚i/8ºkÉ^€ÂZqŒ:ZsŒ½9”d ­Bù )ßsLù-ï7½æx˜ÏJ›¡¾̉`¯aɽ)f¥É$†µ’1™¸ dÑcªCZCù<£7Ă3JÊgóz̀nø₫HȰíá̀YÉäTœ¯a…ï¯Æ,_»œ-Ÿ—Oë87Ë}êÛKÔ´Ü—Ll¹oKṇ̃+Êg­J̀â.¾GZyóº‹Vđc­48¸’ï¼äØWtù]Í:P~`áŒñ±–rZq.nÍ1]Ç ÇàSÿæ/©ßP•ưïuö¿7Ùÿ¾̀₫÷Uö¿·Ùÿ̃eÿû:û?È́ÿ ²ÿƒÎ₫&û?”Ùÿ!dÿ‡&û¿1y–¦¼ÍH·œn5₫¹ă)º½Ưỷ“Bï½x#†1̃´Ă₫€]ôGoáơñÅ×Mñ?®Xê endstream endobj 818 0 obj << /Length 833 /Filter /FlateDecode >> stream xÚmUMoâ0½çWx•Ú‹í„8TÉ·ÔĂ~h[­ö ‰ÛTàĐ¿~3„Àªư<óüfǘÜ}ùù<³M¿ơ³ø«¿ü¡? µŸåß6ûèî®èëÓÎwÇï̃7¾WâçĐ×Ï₫(îó§â©k!ø©«ßO£>r₫­í¦́#î_üŸÙî°Ư)9ÛÚ÷cÛÍ$‚_Úă{út]PÜ‚‚’~ûáĐöƯ£P_¥”(»&ïw(ăÍÏRÄ|÷ÚvÍpÖ#¶P)-¶>gô_ïB?üüq8úƯS÷ÚG«•˜ÿ ‹‡ăđA¢ù¡ñCÛ½‰û[iaéù´ß¿{È2Z¯Eă_c¨ÿûfçÅüÓ/1/{/4ÍëªûÆö›Ú›îÍG+)×bUUëÈwÍk±æ”íëu¬TáOë4[@ˆ 0@`Á%€€! £ˆ Ạ̀#P°™ €Â.w)¡À¡ˆĂºp¨%K€cJ€e Rͤ™¥”ÚÜÈ(ú*¤Ú1:b®¥DDŒ”˜RÔ@‚ È“2Œ£UâR*N)KI˜Î¡Ô€Ă0‡C„‡ƠSƒ,úk“©Éªm:5ÙB“ͦ&[đY{Åœ́@ê’©É)ÎNMv¨ÜåS“ÊpåÔäJs}irpĐh•…­SÿƯ á™Ø2éĐù¬L9ΙÖVă¼â}åy®Xió³Å̀8'z®¸Ư ÊÔxqÓ1ÏGÍyלŒN–Z1f×Xt:æs±ǼûĐÚ0>w’pÖVR.Ơ­rÂ)>ç1q̉¾ùKv´Ḉ‰ĂHX„¶”­¤„1iŚ5r„̉ÈM y°‚R6FBñl´˜¬H>]„³6ê‰áb ×£Ă5&Ă5&0½a'ÔeøvÔbÀ_dfQTtÁŒ£ÇÂQ]z™ÎơKÊ/¯ÆÅWĐ‘Éé^Zz…¤&£·¾²å­¯œºơ•Ó·¾ræÖW.»ơ•«&_åṛUOẓ䢓n9¯)̃₫ËC]Ÿ†!¼áô §rÛùË7dßï‘E?úøŒ_;̀~TÑ?mÑ endstream endobj 819 0 obj << /Length 700 /Filter /FlateDecode >> stream xÚmTÁn£0½ó̃C¥öƆ@LE"¤¶­jµ×œ©D’•ú÷;oƤƯj¥Ÿgæ½y_ưxÜN²º{q“èV«'ẃÎCå&ùÏ]\]]u>¸ötï\íêq÷x§‡®Úº“ºÎ7ŦmN7”¼i«÷síÆ¬ÿ'­ÜkÓ~¦€G]?»ß“₫íÏ`‡ ư4̣›Ó;íßR´V—µâÔ_n86]{§̀­Ö€u[çƯºÁÔs«é¨fß´ơà¨È L¨ê¦:ù?«€âíÇñä›vß‹…>Ñæñ4|°²›`ú0ÔnhÚWu}QEèöÜ÷ï ”–KU»=5£Yïw§¦ß‡ºl?ôN…¼6¢¦êjẃw•ví« Z/Ơ¢,—këo{&–’—ư˜›P®ăaffIÀqÉÀ¼ ÀXMJ0Lf„hr¦˜dÄ¥–€ÄP<çF:AS‹l –PJ̉ˆâtÆ€É #• ¡G–s =2ô+æ¬ (@»–Œ´ës‹°5¤—È.W PL²KF1 ˆơèLơ¶Èđë°HáI(£$ôçuô¹†x-ƒ̀à¥üÚJ¼BœJœ!^I Ñ:ggM«5ă9¤æ7F7̀FŒáN°}Y{}&₫ƒF“È„ûf.œpÑdkæ_ Μ¢‹NÅ0VG9×ú×ʱçĐúw₫DKŒù¬Ä4XĂ=CøaCÉ–g2)4X( ÍÆrb0§/sù4êlƵ¬Ç®‡ËĂÄÜúÉb®]ËŒ̀[r<ƒÎÔs!?ơïf*µŒ{.ø“z.ôI=ÎmZˆoàJ™+Î9ÇRàÊ ñϨxè?Wúđáâr¹\Ơyè¦àˆo|ÿMë.—Tßơ¨â?ßnăư‰ƠCü_er¨ endstream endobj 820 0 obj << /Length 699 /Filter /FlateDecode >> stream xÚmTÁn£0½ó̃C¥öƆ@LE"¤¶­jµ×œ.RˆCÿ~çÍ8i·Z)Aăç™yoÆ7?·“¬îönƯkơâNƯy¨Ü$ÿ¹ëƒ››¢«ÎG×ÎƠ®¾́ÔóĐU[7ªÛ|SlÚf¼£äM[½ŸkwÉú̉ʽ5íg xÔí«û=éÇẵúiä½6ă;íßR´V×µâÔ_n85]û ̀½Ö€u[çƯºOÁÔs«éEÍ¡iëÁ P{È L¨ê¦ưŸƠ‘ @ñöă4ºă¦=tÁb¡¦/´y‡VvLŸ†Ú Mû¦n¯ªƯû₫ƯẢÁr©jw f4ëăîèÔôûP×í×̃©×FÔT]íNư®rĂ®}sÁBë¥Z”å2pmưmÏÄR²?\rÊƠs<̀̀, X#.˜K±Ié†ÉŒ€íC®Ó€Œ¸ÀçÜH'hj‘mÁJIQœÎ09d¤’a"2ôÈrî‘¡G†~Å\€5h×’Q€v]`n¶†ôÙå @v)Â(†A'b}q¦ú³Èđë°HáI(£$ôçuô¹†x-ƒ̀à¥üÚJ¼BœJœ!^I Ñ:ggM«5ă9¤æ7F7̀FŒáN°}Y{}&₫ƒF“È„ûf.œpÑdkæ_ Μ¢‹NÅ0VG9×ú×ʱçĐúw₫DKŒù¬Ä4XĂ=CøaCÉ–g2)4X( ÍÆrb0§/sù4êlƵ¬Ç®‡ËĂÄÜúÉb®]ËŒ̀[r<ƒÎÔs!?ơïf*µŒ{.ø“z.ôI=ÎmZˆoàJ™+Î9ÇRàÊ ñϨxè?Wúđáâr¹^Ơyè¦àˆo|ÿMë®—Tßơ¨â?ßn—û«§2ø %ôrg endstream endobj 821 0 obj << /Length 699 /Filter /FlateDecode >> stream xÚmTÁn£0½ó̃C¥öƆ@LE"¤¶­hµ×œ.RˆCÿ~çÍ8i·Z)Aăç™yoÆ7?·“¬î^Ư$º×êźóP¹I₫sß77EW®«]}Ù==¨ç¡«¶nT·ù¦Ø´ÍxGÉ›¶z?×î’ơÿ¤•{kÚÏđ¨Ûû=éÇă`‡ ư4̣vÍøNûß·­Ơu­8ơ—NM×>(s¯µ&`ƯÖyw„îS0ơÜjzQshÚzđÔ+ä&TuS~ÅÏêH xûqƯqÓº`±PÓÚ<Ă+» ¦OC톦}S·WU„nÏ}ÿî @é`¹Tµ;P3ơqtjú}¨ëöî£w*äµ5UW»S¿¯Ü°oß\°Đz©e¹ \[Û3±”¼.¹ åê9ff–¬— ̀ Œ¥Ø¤ôĂdF@ˆö!×i @F\ ` H Åsn¤4µÈ¶` ¥$(Ng ˜2RÉ0zd9÷ÈĐ#C¿b.À€´kÉ(@».0·[Cz‰́rÅÅ »aĂ ‹±¾8SưÙäøuX¤đ$”Qúó:ú\C¼–AfpGÇR~m%^!N%ί$†h³³&„ƠñR 󛣿#Æ¿p'XϾ¬½>ÿ‹A£Iä Â}3N¸h25ó¯gNÑE'b«£œkưkåØ¿sè ư»¢%Æ|Vâ ¬á!ü°¡äÀË3™¬?Đfc91˜Ó—9Ç|u 6ăZÖcW‚Cƒåƒabî ưd1×®eFæ-9Ag깟ú÷Æ3•ZÆ=üI=ú¤ ç6-Ä7p¥̀çœă?)pe…øÆgT<ôŸ«?}øpq¹\¯ƒê< tSđ Ä·¾ÿ¦u×KªïzTñŸo·Ëư‰ƠSü¨r· endstream endobj 822 0 obj << /Length 700 /Filter /FlateDecode >> stream xÚmTÁn£0½ó̃C¥öƆ@LE"¤¶­jµ×œ.RˆCÿ~çÍ8M»])AăÇ̀¼7ÏÆW?·“¬î^Ü$ºƠêÉ»ÓP¹I₫s×WWEW®ï«]}~{¼SCWmƯ¨®óM±i›ñ†’7mơvªƯ9ëÿI+÷Ú´—đ¨ëg÷{̉‡¡±Ă„~‰ÏÍøF ß̃)ÔPœüË Ç¦kƠZ°në¼;@ú1˜zz5= Ú7m=x ꪺ©F¿âgu P¼}?î°i÷]°X¨é½<Ă;k» ¦C톦}U×YoO}ÿæ Aé`¹TµÛS7÷~wpjúm®÷Ïï½S!¯è©ºÚû]å†]ûê‚…ÖKµ(ËeàÚúŸw&–’—ư97¡\=ÇẰ̀’€5â’yA€±›”a˜̀Ñ>ä:M1ȈK,‰¡xÎt‚¦Ù,¡”¤Å錓@F*&" C,çzdèẀXP€v-h׿akH/‘]® ˜d—"Œbtv"Öggª?»|¿‹„2JB^G—5Äkdwt,uà×VââTâ ñJbˆÖ9;kBX­Ï!Ơ0¿‰0ºa₫0büw‚ớÓÚë3ñW M";÷Í\8á¢É8Ö̀¿œ9Ea¬r®ơÛʱßsè ữ?Ñc>+q ÖpÏ~ØPrà‡å™L Ö h³±œ̀iÅËœc>:‚›q-ë±+Á¡Ạ́Á01÷„~²˜k×2#ó–Ï 3ơ\ÈOư¾ñÁL¥–qÏRÏ…>©ç¹M ñ \)sÅ9çøO \Y!¾ñưçêO>\\/÷Auº*øâ[ßÓºkªïzTñŸï·ó%ƠCü0tÄ endstream endobj 823 0 obj << /Length 700 /Filter /FlateDecode >> stream xÚmTÁn£0½ó̃C¥öƆ@LE"¤¶­jµ×œ.RˆCÿ~çÍ8M»])AăÇ̀¼7ÏÆW?·“¬î^Ü$ºƠêÉ»ÓP¹I₫s×WWEW®ï«]}~{¼SCWmƯ¨®óM±i›ñ†’7mơvªƯ9ëÿI+÷Ú´—đ¨ëg÷{̉‡¡³Ă„~‰ÏÍøF ß̃)ÔPœüË Ç¦kƠZ°në¼;@ú1˜zz5= Ú7m=x ꪺ©F¿âgu P¼}?î°i÷]°X¨é½<Ă;k» ¦C톦}U×YoO}ÿæ Aé`¹TµÛS7÷~wpjúm®÷Ïï½S!¯è©ºÚû]å†]ûê‚…ÖKµ(ËeàÚúŸw&–’—ư97¡\=ÇẰ̀’€5â’yA€±›”a˜̀Ñ>ä:M1ȈK,‰¡xÎt‚¦Ù,¡”¤Å錓@F*&" C,çzdèẀXP€v-h׿akH/‘]® ˜d—"Œbtv"Öggª?»|¿‹„2JB^G—5Äkdwt,uà×VââTâ ñJbˆÖ9;kBX­Ï!Ơ0¿‰0ºa₫0büw‚ớÓÚë3ñW M";÷Í\8á¢É8Ö̀¿œ9Ea¬r®ơÛʱßsè ữ?Ñc>+q ÖpÏ~ØPrà‡å™L Ö h³±œ̀iÅËœc>:‚›q-ë±+Á¡Ạ́Á01÷„~²˜k×2#ó–Ï 3ơ\ÈOư¾ñÁL¥–qÏRÏ…>©ç¹M ñ \)sÅ9çøO \Y!¾ñưçêO>\\/÷Auº*øâ[ßÓºkªïzTñŸï·ó%ƠCü¬2tâ endstream endobj 709 0 obj << /Type /ObjStm /N 100 /First 941 /Length 6184 /Filter /FlateDecode >> stream xÚå[k“Û6–ữ¿‚ăIµ‰÷£*5U¤(åe{²î̀83S®-¹-ÛiwwZêÄ™_¿ç‚Ŕöfjwk«M p/î÷€”¹6«,g•ß¼2Nà[Tœ[†¬s wº’«ÊzQ ­²’LY4T%µ•ו̉̃Yo*­%øzWiïY嫌 Qå$ª2V̉©Œ 0åW̉Xm<‚†¸$ÓgF‚…Ö¼â9æy¦5zDå¹÷•”º̣RI ™Ê+ç ¼¬¼1 ïÀƒtăŒA]. *ăŸq~&­­æs¨†–£–FKJ‹–¡”ầ¢¥ µZNÀD̀c ' ˆ‰™-|B{´Œ9ƒa8U ,œ®zñ`¹`d¥É2dm0´4YcÈ̉dƒ!Z[C&DĂ •&;ëÎ4MöÎVpLÁ˜, P¥i [b]44TÀd!aI“Ö4Ya-RDh l„:#³fRĂÁ/‰î*êa+ÇrÉàH'`%)àG¥‚VÅ¥•’\ˆ–G€9 Ë+Ô™#ÆJAi‡\Ỳvœ•·-XS p ^Ó 6qä mag'±‚k À°)iÀ-¬a¬ÀJPœPÈPXXGVAüQ‹‚Gip!¯YCz ®¹µ²­ç4k ÁEc “¢…5°¸?sdw§If8 .1ÔÂÎ#Q¨œú°†Wâkxc‰ ÖđÎSŸ‡á9éuƒÑâhi+Ͼúê¬₫ñ·ÛMU¯n®÷gơÅư«}¸¥NyV?[¿§1§Î„§ëưƯöCơwö˜Ñ_l½́g´í ÆÑq,ÀRFVy¾ÙƯÜß]nvƠW_Uơw7—›=¦Ơ?t«ª₫öưúí¦­^Vü#˜lïvûÅ»ơ]%±è“ơpƒ(;«_l_ïßíẪªçgợụ́æơöúmØeBÍ%ö»°áPx₫]™ÇÈ0–₫úûØ›ß~~êxι¼̉§²ßqÖÇå₫=¸ư»?_f‘½~VwÛ7o6w›k ¬¿KU¯%ƠúñơÍ₫ơæ 6§z.^)1öJôĐ…ùJă2¸°óºq†G. ZÍq \²̉*ÍĐ C₫i3öĐ|Í3ờ ø‹ËáÂ, ®\-¸ZYÙ‘«Ǻp‚‚‚‚v2f9Đ… :8èà@á@á@á@á@᱆ç( ‰Êc6v ?®æA‡ƯÙ:xp¸xpA‘¡N‚>$}(úĐôaèẲ‡£¢àDÁ‰‚' Nœ(8Qp¢àDÁ‰B… !^R¶’£É‘F÷ L>DuâñxB¥0eâ hàÈáFƒA¢1„âÅ7@(¨gư ö`‹Ú:ܪ0oEX\¡`Y\Q`YdM ‡½ ¾¯¨À7@GÖèÈ›ºÑ‘µ!‘5‹Ñ‘5öt££Ô(EÆÄuCD†,j¢uPÙŒ‰R%@M1&J`±¨‰ ÖŒ‰8Z'Jàh(#¨%æ 3Ü`Q%x"‹7XÔF PóÎ%đäàHăÉÁ‘ÑjT¢!ÖQPO¬£ XGA (Ç̉¡QîDÀ¦ñĐLwĐĐ©t‡¥NwĐÑ™tIœMwŹtY\’uËø$ !cŸdA¹2>É›î ‹O²7Ÿdá„u“,²ø$ ÀñIY|’EP°'YE{’EP¸åÓ ‚‚®Đ†ä1Kmº$`–„–q̀ mºâ<¢¥6Ç1`–Ô¦~â4¾BMC¾ĐǼÈ÷ÿæÏ(ă'ƒ'\'¹€Â%J° —+%\#.̀Ó˜§ƠG”8̀3˜GGN9‚%̀×Ă“ù|°„]j>́ÿ,d¢Ií$¶êÔ0E‡í~s‡‡éàœ®#²²<ÖEÛ²a–j„YtRN0ËÊ fYaF˜eEBcØ”S¡%̀år̀år̀år̀år̀•j,€”M%–Xª°TlRƠô )Ê†× §ÑCs‘ ƒ2!8zl5dD5b;+ơˆí¬4#¶³̉ØÎJ7b;+ưˆí¬b#¶³ ß;Ù„oC¸ËÎÙ„…}lÂBTó ô± ;ZÇpÎ&ä Ø„Uá›Đ2<`ö†lB±đ€M(ÖÓ#5=‚6ËƯÚ,÷#h£:›@›M`ÈÄ&° `bµË@›Ơ>mÖ° ´YĂ3ĐfÈ@›52mÖ¨ ´Y£3ĐfÉ@›56mÖ¸ ´Yă3Đf-Ë@›µ<mÖ ´Y+3Đf­Ê@›µ:mÖ ´Yk3Đf²  m„¶ÚFhK@j„¶‚Rv#'đˆÑÅ ÀˆÀW^2l^ÛÑX\ÂæÏ6¦4Î!Đhc#Đ¢çp6ăŸÀVˆóé[€Û±+>đˆÉé¯₫ÖÀ“q jă[+y"Î@&MYöĐ‹nœó$«î Âdè± Cí>›Ùđ«•ÔËÖ£ÄîèîØ×‡ÈĐGsY&¸–),B?Ô×ă¥2Ẁ/R+¸ŸNXÙ•‡_ÔäØErÓftAᢵKưÑí¹û\/ IïB’†Í(®ø)IV¬«é!Ëœíf& ƒ–}v–&>–úéíL̀²”QƒË́pÁíái…³îă¼Á9Ÿ HÎ4OS-Rg±FÄ!M‡ï¼?Ñ m7´ăx¢2#Í̉t~¶́6»Ë»íí₫æ®?$ö'˧ß}óơó§_.>ư–3 \­ßî*•#ÏáÎÉ(sT:éÙ́.7×{z:€Ẵúö›Íöí»==ƾßôc8ybđÛưúj{Ù\¿½Ú ûÍû¿@Ô³ú§JĨŸé0úE}yó₫ưº¾ƯÜmo^×»«ơî]#ï8ÜÑüG½l«-8Úá™Ă€8?¦ëÅŸ.~|₫Đơù1U‹ªR1₫|UYTÔø£¾º[_₫s³¿Ú¼ÙÇvP°̃ü|¿¾ªo×8$…ÁĐê‡n¯îwSø‡àûæ§ï¾\üơ˜€OϽéß̣X-s|³;jƒơƯƯͯƒÖW›÷`U_mv»̃ï·×÷»úưưƠ~{{ơ[®¶cü!j7ß./¾|zÑ>=¦66¤sà"èu«™ă•™9̃j³#^Ÿhld®ñߦzȇèñ¢ûî¯/¾|¶}ÿê~w±¾~r₫|óö¾¬ê;§×²ôr'H™9’‹\£p›)¸<¢”Ó£RZL”jêEƯƠ_×ßÔ?Ôëú²~[oëÖđ`}]ßÔ·ơ]½«÷ờ…úA‘ûƯ³gƯbPưùÍûg7₫ÉùÓÍëíí£Ï¥âư¦ŒxÎyÆt;jÏüíùÔ§|ª~ °¬WÁßÖß×Oê§ơ³úO0Èóú¢₫±₫sư—úEư×úo0Đ+˜ẹ̀æêæº~]oêÀ²~S¿Ùâß/›úÍÍư,ø.³áơözC̃àó6n?«î6¿l®ëƯö́»w·ÙÔû_oêûú₫úơænwys·©©­?Ô¿Ơÿªÿµ¹»™úàAÛç³ÅâIûbæƒH>.ú@῭ÖM| ù$Í'D  »Ñ |÷Q'Ư€_Ư_]möÉI}Eº¼¹ư­.:íjôÛ»ßnßÁ)Ûú|½ƯÜmvÛ]teq₫ưù₫f¿yưêjæè¡&~»T,|÷Ị́Û§wŸ_\­¯÷ÿ €øovü¹ÿ$ÏÓ®sYÜcøƒÊÄ7‹‹¯?&™©r),>WƠLU¥Û¬\Êy¹Ô ¹LW5Ûh¾FD_ ~ßáu ©?Lµ.•#Ï_Eà«Jªmôôµ—eÈ„!¾'b-5Åc™!Br„¨ ñÛ§MȆ[ô¶ú#©KÏR³́­œ œ%/=1Íó—— •†-—̣öͰ³₫cRŸ~¢ç~̀úÙΰĐ/nÆô¯„2c"¿< ®Ù;8°]ï64rˆ¶'±~dœŒo_”É̃¾PƠ^¾˜ø|ïÇ›?_oá[̣û‘zJ $Êă⋺L–ÉCAœäñ‡̣˜‡Ë3G¨sÄ\ \Ú’<úPûpyæĐq.Ëă'̉ñƯX.{¸@G1à\23—̀èÉ‹¼,–ÔüwM&>WÎ…ơŸáͨm.ïAè‹c?Ă¯O;<„|¸§ÎL\ÎN‰+(m“¸úSÄå÷cơj.²úHDäÙc?Efñp™? T̀%ŸËv(~‘¼P!X¿ỨPloî©xŸá₫Jµ‹/ ¾ß¾FÁä=d¦_¨ößư ”̃÷Í+̃¿(zù9kˆ₫TX‰~C¯Dÿ QƠ¯!úw!•è_9|̃vX£ƠU‰₫U%ûß½²Ï£ÏZCÊW_*Ù¿R yûï^?Ù¿ù¼5ú—xá™nøî7yzÎĐ«á¾_ëÔêØª}S©₫%K¥ûÚRióQôă‰!pø`h ?C†îkø%ö!Ó?Ưï¯vCTƒ|”á×Ùư¯.Â’>Qnè7ßưhSñX=“ĂĐw›_ÂO»ó¤¨y¤Ø¤H ̣lóahÂ)₫:ŒÔ„‘…É2Mf'VµÓUó-¹E"˜(̃ô:çÓƠâkܦï}‡Ơ"ÿ°˜+(å’m8AÉ21+°IF¶î8›øª®gSÆ&[UdÓSÜl“½í){›\ŸoÊI¸`îø’|0·.f’¹ÍÔÜ‘}¿VAA“̀mD‘2f 6ÉÂúTÇWÖ(ḥ”3SÅt1ü §~ˆ́ĂZº÷:ùA³"eL›CJ•Œª̀)'†$L|ơÔæ”‚*ùAMư  ±¥’éå)Ó‹\2•ƒÁJå¦WêT*Ëdz95½ÈcKL/“é%;N)r?È‚Ḍƒ0'بœMA‘,,D‘M …HÉÜüd¤çÖÄÈ­-Í©LæÉÚ|èy])¨ÇåX“æ¦æSÛH‰EOVʱ´tÙ<½e'&qyµZDFæô e₫‹îæ̣üb¿¾Û?¢ÿJúOÿdk:ѵv¥;å¥~Óêl´eàK»êØJ¶-h\Ö.Œă´+×-DĂ…7ƠÙ¨—¢QNs½\qöˆ₫ÛM6Ú·2̀Y!ƯÊ[¬+ÔX?Ù¾ßîg2i^Ε¤I^´~±đva,k– åÆe½lĂ•uͲ]rƒÑ>3†Qϼ3ă\-YÔỊ́ k…ḱªYJ̃zˆ,3cø…ñ ß:‹•;u•ÉiWj…ÅÁÙÀ KĂÛ¹ºEé‹ÔEÅf›Vk'ùJp±¢%2Ơ¾hu·²̉¾³P\úL¼FUk[§–¾q^@øg÷£ª58¸â€+™ñ £2ç¬ƯrZ.Yg– •6óscṼ­:§WL´+(®¬.)~ }‘º¬¸B3c—ÖyƯ_t.W]³4đ^gåRÂ,}ơ£-bÁ*ïøÊ1ÎFef–Ö1¹Xp§ÚǸ’%GëU#–̃¥ËÖm[ædƒ1eƠJa”÷î8P|.}‘º¨xÛIïƠ“8₫@ªx.̃²ƒ2‹"ª©,Ú•j́rád»4|áȧ™ÇLkÑ6ÎJd/…:÷ù(,¥è?("“:¦hÏÈŒ†đ'KC/yƒ$’}éŸ+~ }‘º¨ø’5 ²˜1‹ƒ m™â‹LÔÂ:)I=/ ÈÇ:¹tN±̣™Áf´v üí¸Ë…0¤¸ÊF­ïăζˆnÚÜàó¾YtvÙjD0í<ưºsŤ/Rï\«Ugp]hÀåªy†s¥ç[œÿ%m_¹đ«ÖÈÆ[ä‚ÑnÍM6º+Á ³+Mß̉n-3Ơ–N«bqå—Êz2©ÈâaéµE¬¡´Ki(Mt1Ô¤/R'«hÉ­W®]:Àg¯ªV‡€äK¤8+•*gP0Ç&¨ZRÍë|´a SxĂW­¤P7Y¬ ̉&ÅYZEI4̉Â%s¨rÙ@qa‹H_¤.)]É{¡['¼ZéVQ@L!2Úqß-µD¸ cóQÅ¡g·ZJF£̀FƠÊp̃Âó²íZNyê²Q+»%6¥NCFÑ̃’Ó.`đqÜv]C¡.zx6SüPú"uYñ®S+!RÙ`` >îÛ(6ÂjNÛèV/y-ó o #X"r!©ÚJ—©Æ»%sÆÙ ¿XѲ‚…J ÊkÇp­h\rB†jh[Ñx.%í²¨ø\ú"uQq¡Ú…Çâ°ØÊ*+¹å…ѾF¥è̉d–lÀ¨“ºåN/T½‰ç³Q”1&Qh±pP4‚±‹Nz1G>5™Á±ÓÉ%Ø Ú ̃H_ªă‡̉©‹c»>ß¶K²­ÊvuŒzRa[‰ 5-mP™_¤Ö+C»ºheçÂMNH8³\v¦¡Q–™e[Ä̉jaơ‚[ª™Ydä6+' à˜TKWRü@ú"uYñ…Q0 vYO>µYKlë¨EPÑv‹!(y\1€:xî´B]#Å3£)À6 £#ÂnêË8cçk™!‘_JRœg«–wÿi„ƒ#@+xQñ¹ôEê¢âjƠ*½lQ¥5r#ø%ó&7ÀÓÈôÎÑîƠb$:’H́°¬¡©¦rW©Ëo8ÏGPÔP™ ˆ"\K$ñbÅQ¤M‡ă•Ñ¢ẩ©‹ë >̃î|Ø]³jKÙÛ 0ÖY¢hQÑÎp@6’ƠRµ™ÑàNµX6vÑÁ,<ç¸AŸà¨iL,Y¨"Sy¢D˜i^Tü@ú"uQq®€» ”êŒ1TOM–‰¦Å®¹TÎrIx21W|å9Đ<½nI‡Q•Œ¶KƯ"ZÄÊ+%¨Pf·ă¤'œexLê²Í ¤ ¥é¸ĂY‹̀R‚¬‡̉©_ß̃n®_o?üá1Hâ¡,v>†0z̃åbMJ}°¨Ñå»ơí~s÷‡Ç„ñ†·±ó1Ụ¹đ ²™¢Æ¡`¿)_*v³.: .¸Üî7/ï~ÛÑ«²Ǹ¥®!Fo×o7$"? ­lí8í@¾¾Ÿ0œ0¤ă6yíô=tö³“̣tD}¦]æÀ|iƠ4ëˆ`”oLå éÉF,6}O8®ˆ¼''D}n/¶j"»¤§QÆ–å²ÆYe¹Â¶j'KHªü“%`ṃBç&NưqŸ á@ÉRÉöÇŒIîDz\Ás̉Éa½Ưær¿½¹₫CH¶X!Rgˆ05ë$qY9øÉdÙ¼‡±Çœ–³¾è£Ơø¼3xqÚ)ˆz&+:ĂÁj̃Iáz1&“J,Èmr&ˆ$z5DQ§æóNH§gä Í4r̃‰™‡!9‘c2ù¨Èm0̣lÍ–ØG´?vÂLNÎ;±’›tA<ă¹xwÿ*³dˆ ă‚·½­ç$‡̉ç3‚§yD]“!Ù"QâƒËÙP(Y¦8D¡6¼ÇQ `y(ë!Ư)ÅÊñ)êlˆ:…Ù©”+ùP0‹à¾8D E™*<ñ”'%e1e¦3N̉ÅE©ŒÊ’<ªÏpu0${ç eËCṬ5+…âÏOª(û́: <¥£́ƒJè²HdXí‹C×âYƸâPxQV‘¶~kNh8ÈzH÷1©†Ø²> endobj 863 0 obj << /Type /ObjStm /N 15 /First 126 /Length 563 /Filter /FlateDecode >> stream xÚ­UMoÔ0½çWøH‘Hü13¶¥ªR6a/”‚ •P¡ª•ÚƯ›ø÷Œ“)‚ÄƯ‚ÄiÏÇ{o<¶Y¥U PÖ¶¨[R=[¯¼Nÿ́3‘mTÑZ¼VFđFc9Â[ÅÖÁ;e\ơ  ŒÁÈ1}2H)ØóG€âô´¨.º‡₫ ¾¾:<~;ô7Ăf·-W¥+ư‰«™Û'ơ§ J“\6ï̉́ÈûR>S̉&_¾frÙ±äuQo6Cî2ïº8;{^#”.U¦,($WȺ]./‘’+_0ơÓå †Ô3}TàÈu™÷’À˜*/»Ú”fÜD̉YWjø8–ÇøÄ“L̃/>ï6·œ¤¹Áz±Alœ¬ÓbÍ­ƯƯ¼ù .--… G!B¥2̀‘ÙsÓ€ÎÏ?-ĐHtđ'ü·+$?Ñ$H4h ÑàEƒ?:Ñ/’÷öơ²…₫’̀¬LÛ8:½œ₫´xùcß«ªé†î~wWTyÆ8fº ‹êĂăp¿Ù+S–\MéíSüûƯm_]ú‹Ư¶ç”}¿­G|~Óè ê'́Ñœ endstream endobj 879 0 obj << /Type /XRef /Index [0 880] /Size 880 /W [1 3 1] /Root 877 0 R /Info 878 0 R /ID [<6ADAD31853A38AC8B329033D27A26AAA> <6ADAD31853A38AC8B329033D27A26AAA>] /Length 2248 /Filter /FlateDecode >> stream xÚ%×ytVÅÇñ™÷ IÈF–y@B@BBI @6–@X’ˆuCª­¢.-*­u©V­mU—QĐº#ʹ´•b­K¡¶¥V,­ÔSÏiÏ©=mŸïÓ>çÎsß{ß{g~wî\cŒùò˜˜±&/aØŒ™X4Ÿ- 1!Xjơ4ăDm(µ:C ™Z&µy4S •Úpjµ4‡Bµ‘Ôjh¦Cµ"jsifBµiÔæĐÙÔê¨UÓ̀\j‹©Í¦™Ă©-¡6‹æ¿´‰aÔªh‚|j9Ôf̉ Ô¦R«¤é Am>µ4ÇÀXj ¨M§9 ©µP« 9&P[JmÍ"(¦ÖF­œæD(‘Bm*ÍR˜D-—Ú“¡ŒÚDje4uÇTj‹¨éOô¤Ó¨µR›DS/h:µƠÔôôz3r—1WE­„¦v„övöé\k̀0͆vû~\ôDzCY“Sc}J˜Ç^í0fh4ÂBh‚fhE°Za ,…eĐíĐĐËa¬„UĐ «a ôÀZØ Ö$9½Èu°+Ơfl„~‚¤ñîµ&ơ´î ÆVˆq¡ <!‰¦&{$`=¾z¬¹è9=ŒG#ƯlMb§ÖôIÑGƒ"è¡O¹ûBȵ¦¸C èd¢̣a4cÉÍ„ »! @`Œ9 „&Œ·¦́ jI ä @r‘ eÜŒËÓ¦ZSuB%kpƒ@¤N H ‚R >Ñ©ù¯é ˜É ̀€2€€H ÑÖ4Wë Ƚcy D%•ĐÆS‡! ƯN^±Ö´/ן@|ñ Ä'Ÿ@h9«­Yóÿ1'C íçơ@B/ôñGLs¡ß₫Cz„æè² 1H‚dH¥w ­9Ö¦?É€4k¶Tj3FiJdZ³ơNƯ‘Ù y0F€Nx:›éô•oͶSz˜ƒR˜c¬ùv¯îĐ)mèD6tú*´˜‘“y(Q %ÖܱKO0ÊÙ'Q̀9‰P U0 æÂLkøDM脬ó‹₫ù<¹dïÛú“ZXuÖ́Û¬µzh ËÙj„ÅĐdÍ-ú“fX« Ơ—Oè%° Ú¡:¡ ô|+`%ϯÑmÍ‘ƯZ k xÄë`=l€^ĐDl„~€Ak“ßä,~Xk̃IÖ&±đ$Ö“ O6| ¤ÂPHáI‰Ï„,:Œ̣Œ›Ï¶æä8=_ O,<±đÄÂë´Dg{råI‰'¨ø1@aÁ B#'m*/Z®=",~Zh}EXr\XzVh*´7 -zá,¨Üè…># æFè‡é°·\ë[(l\#ô‚“ÂÀ] ·p̃\à6}(œL¸àáB`3‡]t™đµ=ÂÅ\Ú% —î.ẵ.¿FØR%\ÁÍled¾¾J¸’>½ê*á× ß|L¸₫»æˆ°í áZ®åº¯„íơÂ₫íúAá†Û…ƒpñ­ ;‹„›ó…[®n½BصLø9ø.y₫=núö1Â\ƠÂ]÷ ß¿[¸û°pÏ3Âî}P¸ïYá~böÁüQ&|.ü¤Dxđ|á¡mÂĂo8Î(Dúé¦+Uf(ÉÚƯœônëÑ·„=G…½dă1.wßa?<^ÿ 4Ỏ‰Oq¿¡IxºÎ Ï| ¸O8Ø%<Ëà=—-ü´Sx¾GxáBáEÆ̣¥ /óD½̉/¼Ê­ê^spF8ügáu­7₫)á ¢ á(#ư³‘Âϳ„_$„7¹Œcdă—́=΀¾Å£û«K…·o~½UxçuáƯƒÂ{Ỗ'9¿áOlNr‘¿ex>h~GO₫₫VáĂ«…?Ü(œbÜ>Z)|Ü'œæÿÈ̃Oè—?ñ¸|úpæ€đÙÇÂÙáÂ_ „¿ÖŸÓ»çn₫¶_G†©>bªtư§ßÓiÖ~ñ…îM·±̀Ëu+ĂÆÊêV¦µæéV–u=¡[ĂllÓGº•mc»wèV}U·rm <#Include SYSTEM "title.xml"> Introduction <#Include SYSTEM "intro.xml"> Bits and Pieces <#Include SYSTEM "misc.xml"> Algorithms of Orbit-Stabilizer Type <#Include SYSTEM "spacegroups.xml"> Resolutions of Crystallographic Groups <#Include SYSTEM "fundamentaldomain.xml"> <#Include SYSTEM "geometry.xml"> <#Include SYSTEM "resolutionAccess.xml"> hapcryst-0.2.0/doc/chooser.html0000644000175100017510000000745615160525022016063 0ustar runnerrunner GAPDoc Style Chooser

Setting preferences for GAPDoc manuals

Unfold subsections in menus only by mouse clicks: no (default)     yes

Show GAP examples as in sessions with ColorPrompt(true): yes (default)     no

Display side of table of contents within chapters: right (default)     left

Main document font: Helvetica/sans serif (default)     Times/serif

Paragraph formatting: left-right justified (default)     ragged right

Apply settings to last page.

hapcryst-0.2.0/doc/chapA.txt0000644000175100017510000001274115160525022015301 0ustar runnerrunner A Resolutions in Hap This document is only concerned with the representation of resolutions in Hap. Note that it is not a part of Hap. The framework provided here is just an extension of Hap data types used in HAPcryst and HAPprime. From now on, let G be a group and dots -> M_n-> M_n-1->dots-> M_1-> M_0-> Z be a resolution with free ZG modules M_i. The elements of the modules M_i can be represented in different ways. This is what makes different representations for resolutions desirable. First, we will look at the standard representation (HapResolutionRep) as it is defined in Hap. After that, we will present another representation for infinite groups. Note that all non-standard representations must be sub-representations of the standard representation to ensure compatibility with Hap. A.1 The Standard Representation HapResolutionRep For every M_i we fix a basis and number its elements. Furthermore, it is assumed that we have a (partial) enumeration of the group of a resolution. In practice this is done by generating a lookup table on the fly. In standard representation, the elements of the modules M_k are represented by lists -"words"- of pairs of integers. A letter [i,g] of such a word consists of the number of a basis element i or -i for its additive inverse and a number g representing a group element. A HapResolution in HapResolutionRep representation is a component object with the components  group, a group of arbitrary type.  elts, a (partial) list of (possibly duplicate) elements in G. This list provides the "enumeration" of the group. Note that there are functions in Hap which assume that elts[1] is the identity element of G.  appendToElts(g) a function that appends the group element g to .elts. This is not documented in Hap 1.8.6 but seems to be required for infinite groups. This requirement might vanish in some later version of Hap [G. Ellis, private communication].  dimension(k), a function which returns the ZG-rank of the Module M_k  boundary(k,j), a function which returns the image in M_k-1 of the jth free generator of M_k. Note that negative j are valid as input as well. In this case the additive inverse of the boundary of the jth generator is returned  homotopy(k,[i,g]) a function which returns the image in M_k+1, under a contracting homotopy M_k -> M_k+1, of the element [[i,g]] in M_k. The value of this might be fail. However, currently (version 1.8.4) some Hap functions assume that homotopy is a function without testing.  properties, a list of pairs ["name","value"] "name" is a string and value is anything (boolean, number, string...). Every HapResolution (regardless of representation) has to have ["type","resolution"], ["length",length] where length is the length of the resolution and ["characteristic",char]. Currently (Hap 1.8.6), length must not be infinity. The values of these properties can be tested using the Hap function EvaluateProperty(resolution,propertyname). Note that making HapResolutions immutable will make the .elts component immutable. As this lookup table might change during calculations, we do not recommend using immutable resolutions (in any representation). A.2 The HapLargeGroupResolutionRep Representation In this sub-representation of the standard representation, the module elements in this resolution are lists of groupring elements. So the lookup table .elts is not used as long as no conversion to standard representation takes place. In addition to the components of a HapResolution, a resolution in large group representation has the following components:  boundary2(resolution,term,gen), a function that returns the boundary of the genth generator of the termth module.  groupring the group ring of the resolution resolution.  dimension2(resolution,term) a function that returns the dimension of the termth module of the resolution resolution. The effort of having two versions of boundary and dimension is necessary to keep the structure compatible with the usual Hap resolution. hapcryst-0.2.0/doc/chap3.txt0000644000175100017510000003211315160525022015256 0ustar runnerrunner 3 Algorithms of Orbit-Stabilizer Type We introduce a way to calculate a sufficient part of an orbit and the stabilizer of a point. 3.1 Orbit Stabilizer for Crystallographic Groups 3.1-1 OrbitStabilizerInUnitCubeOnRight OrbitStabilizerInUnitCubeOnRight( group, x )  method Returns: A record containing  .stabilizer: the stabilizer of x.  .orbit set of vectors from [0,1)^n which represents the orbit. Let x be a rational vector from [0,1)^n and group a space group in standard form. The function then calculates the part of the orbit which lies inside the cube [0,1)^n and the stabilizer of x. Observe that every element of the full orbit differs from a point in the returned orbit only by a pure translation. Note that the restriction to points from [0,1)^n makes sense if orbits should be compared and the vector passed to OrbitStabilizerInUnitCubeOnRight should be an element of the returned orbit (part).  Example  gap> S:=SpaceGroup(3,5);; gap> OrbitStabilizerInUnitCubeOnRight(S,[1/2,0,9/11]);  rec( orbit := [ [ 0, 1/2, 2/11 ], [ 1/2, 0, 9/11 ] ],   stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ],   [ 0, 0, 0, 1 ] ] ]) ) gap> OrbitStabilizerInUnitCubeOnRight(S,[0,0,0]);  rec( orbit := [ [ 0, 0, 0 ] ], stabilizer := )  If you are interested in other parts of the orbit, you can use VectorModOne (2.1-2) for the base point and the functions ShiftedOrbitPart (3.1-9), TranslationsToOneCubeAroundCenter (3.1-10) and TranslationsToBox (3.1-11) for the resulting orbit Suppose we want to calculate the part of the orbit of [4/3,5/3,7/3] in the cube of sidelength 1 around this point:  Example  gap> S:=SpaceGroup(3,5);; gap> p:=[4/3,5/3,7/3];; gap> o:=OrbitStabilizerInUnitCubeOnRight(S,VectorModOne(p)).orbit; [ [ 1/3, 2/3, 1/3 ], [ 1/3, 2/3, 2/3 ] ] gap> box:=p+[[-1,1],[-1,1],[-1,1]]; [ [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ] ] gap> o2:=Concatenation(List(o,i->i+TranslationsToBox(i,box)));; gap> # This is what we looked for. But it is somewhat large: gap> Size(o2); 54  3.1-2 OrbitStabilizerInUnitCubeOnRightOnSets OrbitStabilizerInUnitCubeOnRightOnSets( group, set )  method Returns: A record containing  .stabilizer: the stabilizer of set.  .orbit set of sets of vectors from [0,1)^n which represents the orbit. Calculates orbit and stabilizer of a set of vectors. Just as OrbitStabilizerInUnitCubeOnRight (3.1-1), it needs input from [0,1)^n. The returned orbit part .orbit is a set of sets such that every element of .orbit has a non-trivial intersection with the cube [0,1)^n. In general, these sets will not lie inside [0,1)^n completely.  Example  gap> S:=SpaceGroup(3,5);; gap> OrbitStabilizerInUnitCubeOnRightOnSets(S,[[0,0,0],[0,1/2,0]]); rec( orbit := [ [ [ -1/2, 0, 0 ], [ 0, 0, 0 ] ],   [ [ 0, 0, 0 ], [ 0, 1/2, 0 ] ],  [ [ 1/2, 0, 0 ], [ 1, 0, 0 ] ] ],  stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ],   [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ]) )  3.1-3 OrbitPartInVertexSetsStandardSpaceGroup OrbitPartInVertexSetsStandardSpaceGroup( group, vertexset, allvertices )  method Returns: Set of subsets of allvertices. If allvertices is a set of vectors and vertexset is a subset thereof, then OrbitPartInVertexSetsStandardSpaceGroup returns that part of the orbit of vertexset which consists entirely of subsets of allvertices. Note that,unlike the other OrbitStabilizer algorithms, this does not require the input to lie in some particular part of the space.  Example  gap> S:=SpaceGroup(3,5);; gap> OrbitPartInVertexSetsStandardSpaceGroup(S,[[0,1,5],[1,2,0]], > Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]])); [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 2, 6 ], [ 2, 3, 1 ] ] ] gap> OrbitPartInVertexSetsStandardSpaceGroup(S, [[1,2,0]], > Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]])); [ [ [ 0, 1, 5 ] ], [ [ 1, 1, 0 ] ], [ [ 1, 2, 0 ] ], [ [ 1, 2, 6 ] ], [ [ 2, 3, 1 ] ] ]  3.1-4 OrbitPartInFacesStandardSpaceGroup OrbitPartInFacesStandardSpaceGroup( group, vertexset, faceset )  method Returns: Set of subsets of faceset. This calculates the orbit of a space group on sets restricted to a set of faces. If faceset is a set of sets of vectors and vertexset is an element of faceset, then OrbitPartInFacesStandardSpaceGroup returns that part of the orbit of vertexset which consists entirely of elements of faceset. Note that,unlike the other OrbitStabilizer algorithms, this does not require the input to lie in some particular part of the space. 3.1-5 OrbitPartAndRepresentativesInFacesStandardSpaceGroup OrbitPartAndRepresentativesInFacesStandardSpaceGroup( group, vertexset, faceset )  method Returns: A set of face-matrix pairs . This is a slight variation of OrbitPartInFacesStandardSpaceGroup (3.1-4) that also returns a representative for every orbit element.  Example  gap> S:=SpaceGroup(3,5);; gap> OrbitPartInVertexSetsStandardSpaceGroup(S,[[0,1,5],[1,2,0]], > Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]])); [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 2, 6 ], [ 2, 3, 1 ] ] ] gap> OrbitPartInFacesStandardSpaceGroup(S,[[0,1,5],[1,2,0]], > Set( [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [[1/17,6,1/2],[1,2,7]]])); [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ] ] gap> OrbitPartAndRepresentativesInFacesStandardSpaceGroup(S,[[0,1,5],[1,2,0]], > Set( [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [[1/17,6,1/2],[1,2,7]]])); [ [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ],  [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ] ]  3.1-6 StabilizerOnSetsStandardSpaceGroup StabilizerOnSetsStandardSpaceGroup( group, set )  method Returns: finite group of affine matrices (OnRight) Given a set set of vectors and a space group group in standard form, this method calculates the stabilizer of that set in the full crystallographic group.  Example  gap> G:=SpaceGroup(3,12);; gap> v:=[ 0, 0,0 ];; gap> s:=StabilizerOnSetsStandardSpaceGroup(G,[v]);  gap> s2:=OrbitStabilizerInUnitCubeOnRight(G,v).stabilizer;  gap> s2=s; true  3.1-7 RepresentativeActionOnRightOnSets RepresentativeActionOnRightOnSets( group, set, imageset )  method Returns: Affine matrix. Returns an element of the space group S which takes the set set to the set imageset. The group must be in standard form and act on the right.  Example  gap> S:=SpaceGroup(3,5);; gap> RepresentativeActionOnRightOnSets(G, [[0,0,0],[0,1/2,0]], >  [ [ 0, 1/2, 0 ], [ 0, 1, 0 ] ]); [ [ 0, -1, 0, 0 ], [ -1, 0, 0, 0 ], [ 0, 0, -1, 0 ], [ 0, 1, 0, 1 ] ]  3.1-8 Getting other orbit parts HAPcryst does not calculate the full orbit but only the part of it having coefficients between -1/2 and 1/2. The other parts of the orbit can be calculated using the following functions. 3.1-9 ShiftedOrbitPart ShiftedOrbitPart( point, orbitpart )  method Returns: Set of vectors Takes each vector in orbitpart to the cube unit cube centered in point.  Example  gap> ShiftedOrbitPart([0,0,0],[[1/2,1/2,1/3],-[1/2,1/2,1/2],[19,3,1]]); [ [ 1/2, 1/2, 1/3 ], [ 1/2, 1/2, 1/2 ], [ 0, 0, 0 ] ] gap> ShiftedOrbitPart([1,1,1],[[1/2,1/2,1/2],-[1/2,1/2,1/2]]); [ [ 3/2, 3/2, 3/2 ] ]  3.1-10 TranslationsToOneCubeAroundCenter TranslationsToOneCubeAroundCenter( point, center )  method Returns: List of integer vectors This method returns the list of all integer vectors which translate point into the box center+[-1/2,1/2]^n  Example  gap> TranslationsToOneCubeAroundCenter([1/2,1/2,1/3],[0,0,0]); [ [ 0, 0, 0 ], [ 0, -1, 0 ], [ -1, 0, 0 ], [ -1, -1, 0 ] ] gap> TranslationsToOneCubeAroundCenter([1,0,1],[0,0,0]); [ [ -1, 0, -1 ] ]  3.1-11 TranslationsToBox TranslationsToBox( point, box )  method Returns: List of integer vectors or the empty list Given a vector v and a list of pairs, this function returns the translation vectors (integer vectors) which take v into the box box. The box box has to be given as a list of pairs.  Example  gap> TranslationsToBox([0,0],[[1/2,2/3],[1/2,2/3]]); [ ] gap> TranslationsToBox([0,0],[[-3/2,1/2],[1,4/3]]); [ [ -1, 1 ], [ 0, 1 ] ] gap> TranslationsToBox([0,0],[[-3/2,1/2],[2,1]]); Error, Box must not be empty  hapcryst-0.2.0/PackageInfo.g0000644000175100017510000000556315160525022015302 0ustar runnerrunnerSetPackageInfo( rec( PackageName := "HAPcryst", Subtitle := "A HAP extension for crystallographic groups", Version := "0.2.0", Date := "24/03/2026", # dd/mm/yyyy format License := "GPL-2.0-or-later", Persons := [ rec( LastName := "Roeder", FirstNames := "Marc", IsAuthor := true, IsMaintainer := true, Email := "roeder.marc@gmail.com", ), rec( LastName := "GAP Team", FirstNames := "The", IsAuthor := false, IsMaintainer := true, Email := "support@gap-system.org", ), ], # Status := "accepted", Status := "deposited", PackageWWWHome := "https://gap-packages.github.io/hapcryst/", README_URL := Concatenation( ~.PackageWWWHome, "README.md" ), PackageInfoURL := Concatenation( ~.PackageWWWHome, "PackageInfo.g" ), SourceRepository := rec( Type := "git", URL := "https://github.com/gap-packages/hapcryst", ), IssueTrackerURL := Concatenation( ~.SourceRepository.URL, "/issues" ), ArchiveURL := Concatenation( ~.SourceRepository.URL, "/releases/download/v", ~.Version, "/hapcryst-", ~.Version ), ArchiveFormats := ".tar.gz", AbstractHTML := "This is an extension to the HAP package by Graham Ellis. It implements geometric methods for the calculation of resolutions of Bieberbach groups.", PackageDoc := rec( # use same as in GAP BookName := "HAPcryst", ArchiveURLSubset := ["doc"], HTMLStart := "doc/chap0_mj.html", PDFFile := "doc/manual.pdf", SixFile := "doc/manual.six", LongTitle := "The crystallographic group extension to HAP", ), Dependencies := rec( GAP := ">=4.12", NeededOtherPackages := [ ["Polycyclic",">=2.8.1"], ["AClib",">=1.1"], ["cryst",">=4.1.5"], ["HAP",">=1.8"], ["polymaking",">=0.8.6"], ], SuggestedOtherPackages := [ [ "Carat", ">=1.1" ], ["CrystCat",">=1.1.2"], ["GAPDoc", ">= 0.99"] ], ExternalConditions := ["polymake (https://polymake.org) must be installed to calculate resolutions"] ), AvailabilityTest := ReturnTrue, TestFile := "tst/testall.g", Keywords := ["homological algebra","crystallographic groups","resolution"], AutoDoc := rec( TitlePage := rec( Acknowledgements := """ This work was supported by Marie Curie Grant No. MTKD-CT-2006-042685 """, Copyright := """ ©right; 2007 Marc Röder.

This package is distributed under the terms of the GNU General Public License version 2 or later (at your convenience). See the file LICENSE or https://www.gnu.org/copyleft/gpl.html """, Version := Concatenation( "Version ", ~.Version ), ) ), )); hapcryst-0.2.0/init.g0000644000175100017510000000136015160525022014065 0ustar runnerrunnerReadPackage("HAPcryst","lib/environment.gd"); ReadPackage("HAPcryst","lib/misc.gd"); ReadPackage("HAPcryst","lib/spacegroups.gd"); ReadPackage("HAPcryst","lib/translations.gd"); ReadPackage("HAPcryst","lib/geometry.gd"); #ReadPackage("HAPcryst","lib/hasse.gd"); ReadPackage("HAPcryst","lib/resolutionBieberbach.gd"); ReadPackage("HAPcryst","lib/FundamentalDomain.gd"); ####### a few things about datatypes and conversion ####### aka. "the nerdy stuff" ReadPackage("HAPcryst","lib/GroupRing.gd"); ReadPackage("HAPcryst","lib/datatypes/resolutionAccess_generic.gd"); ReadPackage("HAPcryst","lib/datatypes/resolutionAccess_GroupRing.gd"); ReadPackage("HAPcryst","lib/CWcomplexThings.gd"); ReadPackage("HAPcryst","lib/CWcomplexThings_GroupRingRep.gd"); hapcryst-0.2.0/examples/0000755000175100017510000000000015160525022014570 5ustar runnerrunnerhapcryst-0.2.0/examples/3dimBieberbachFD.gap0000644000175100017510000001424215160525022020261 0ustar runnerrunner# (C)2007-2008 by Marc Roeder, # distribute under the terms of the GPL version 2.0 or later LoadPackage("hapcryst"); #### # Adjust these variables, if needed: # JAVAVIEW_PROGRAM:=Filename(DirectoriesSystemPrograms(),"javaview"); #JAVAVIEW_OUTPUT_DIR:=Directory("~/flatManifolds3d/tmp"); JAVAVIEW_OUTPUT_DIR:=DirectoryTemporary(); PRECISION:=9; ## PRECISION is the number of digits after the first non- zero digit ## after the comma. ## If your polytope looks too strange, increase this number. JAVAVIEW_WRAPPER_FILE:=Filename(DirectoriesPackageLibrary("hapcryst","examples"),"javaviewwrapper.txt"); ReadPackage("hapcryst","examples/orbitcoloring.gap"); ############ ### The following 3-dimensional space groups are Bieberbach. ### So you might try viewFundamentalDomain for those: bieberbachlist:=[ 1, 4, 7, 9, 19, 33, 34, 76, 142, 165 ]; ############################################################################# ## ## PLEASE READ THIS: ## ## to get a picture of a fundamental domain of a 3-dimensional Bieberbach ## group, just type ## viewFundamentalDomain([a,b,c],n); ## with a,b,c rational numbers and n a number from the bieberbachlist. ## ## or type ## viewTessellation([a,b,c],n); ## to get a part of the tessellation defined by the fundamental domain. ## The shown geometry contains hidden parts. Look at "Inspector>Display" ## The neighbouring parts are named by the face of the original fundamental ## cell they touch. You can view the names by making the fundamental domain ## "FD" active and tick the box at "Method>Show>Show Element Names". ## ## Use "Inspector>Camera" to zoom in and out. ############################################################################# ## ## This function takes a fundamental domain and colors the faces. ## It also calculates a set of images under and generates a ## JavaView file containing all that. ## writeFundamentalDomainAndImages:=function(poly,maps,group,point,groupnr) local startpointstring, filename, vertexonlypoly, abstract, title, detail, data, outputfile; startpointstring:=ReplacedString(JoinStringsWithSeparator(List(point,String),"_"),"/","."); filename:=Concatenation([numberWithLeadingZeros(groupnr,3), "__", startpointstring]); vertexonlypoly:=CreatePolymakeObjectFromFile(JAVAVIEW_OUTPUT_DIR,Concatenation(filename,".poly")); ClearPolymakeObject(vertexonlypoly); AppendVertexlistToPolymakeObject(vertexonlypoly,Polymake(poly,"VERTICES")); Unbind(vertexonlypoly); abstract:="Fundamental cell of cystallographic group "; Append(abstract,String(groupnr)); title:=Concatenation("FD ",String(groupnr)); detail:="This is the fundamental cell of the crystallographic group number "; Append(detail,String(groupnr)); Append(detail," from GAPs crystallographic groups library.\n The orbits are colored in each dimension.\n"); Append(detail,"Starting point for Dirichlet-Voronoi: "); Append(detail,String(point)); Append(detail,".\nOutput precision: "); Append(detail,String(PRECISION)); Append(detail," (this is the number of digits after the first non-zero entry after the point."); Append(detail,"\nGenerated using the GAP packages HAPcryst and polymake as well as the computational geometry package polymake."); data:=javaviewDatastring(poly,maps,group,PRECISION); Append(filename,".jvx"); outputfile:= OutputTextFile(Filename(JAVAVIEW_OUTPUT_DIR,filename), false ); WriteAll(outputfile, javaviewWrappedDatastring( title, abstract, detail, data, JAVAVIEW_WRAPPER_FILE) ); CloseStream(outputfile); return Filename(JAVAVIEW_OUTPUT_DIR,filename); end; ############################################################################# ## ## This just generates the fundamental domain and writes a JavaView file for it ## writeFundamentalDomain:=function(poly,group,point,groupnr) return writeFundamentalDomainAndImages(poly,[IdentityMat(4)],group,point,groupnr); end; ############################################################################# ## ## generateFundamentalDomain:=function(point,groupnr) local group, poly, filename,vo; group:=SpaceGroup(3,groupnr); # poly:=FundamentalDomainStandardSpaceGroup(point,group); poly:=FundamentalDomainBieberbachGroupNC(point,group); if not IsFundamentalDomainStandardSpaceGroup(poly,group) then Error("failed generating fundamental domain"); fi; filename:=writeFundamentalDomain(poly,group,point,groupnr); return filename; end; viewFundamentalDomain:=function(point,groupnr) local filename; filename:=generateFundamentalDomain(point,groupnr); Exec(Concatenation([JAVAVIEW_PROGRAM," ",filename])); return filename; end; generateTessellationFromPolytope:=function(point,poly,groupnr) local group, facets, vertices, orbitdecomp, maps, facet, orbit, otherfacet, filename; group:=SpaceGroup(3,groupnr); Polymake(poly,"FACETS VERTICES_IN_FACETS FACE_LATTICE"); facets:=Polymake(poly,"VERTICES_IN_FACETS"); vertices:=Polymake(poly,"VERTICES"); orbitdecomp:=edgeOrbitDecomposition(facets,vertices,group); maps:=[IdentityMat(4)]; for facet in facets do orbit:=First(orbitdecomp,o->facet in o); otherfacet:=First(orbit,f->f<>facet); Add(maps,RepresentativeActionOnRightOnSets(group,Set(otherfacet,i->vertices[i]),Set(facet,i->vertices[i]))); od; filename:=writeFundamentalDomainAndImages(poly,maps,group,point,groupnr); return filename; end; generateTessellation:=function(point,groupnr) local group, poly, filename; group:=SpaceGroup(3,groupnr); # poly:=FundamentalDomainStandardSpaceGroup(point,group); poly:=FundamentalDomainBieberbachGroupNC(point,group); filename:=generateTessellationFromPolytope(point,poly,groupnr); return filename; end; viewTessellation:=function(point,groupnr) local filename; filename:=generateTessellation(point,groupnr); Exec(Concatenation([JAVAVIEW_PROGRAM," ",filename])); return filename; end; hapcryst-0.2.0/examples/hasse_diagram_reformat.gd0000644000175100017510000000010315160525022021564 0ustar runnerrunnerDeclareOperation("HasseDiagramAsList",[IsRecord]); hapcryst-0.2.0/examples/hasse_diagram_reformat.gi0000644000175100017510000000646515160525022021612 0ustar runnerrunnerInstallMethod(HasseDiagramAsList,[IsRecord], function(hasse) local faceblocks, facenumber, nodes, permlist, pi, node, maxnode, i, upface, blockindex, downshift, upshift, face; # #make a mutable copies: ## faceblocks:=List(hasse.faceindices,i->List(i)); nodes:=List(hasse.hasse,face->[List(face[1]),List(face[2])]); facenumber:=Size(hasse.hasse); if nodes[1][2]=[] then Info(InfoPolymaking,1,"polymake returned dual Hasse diagram. Recovering original"); #### # if the Hasse diagram ends in a list of points, # we do some strange permutation and renumbering to get a Hasse # diagram starting with points (and the dimension of the faces # increases as we proceed down) #### Apply(faceblocks,i->Reversed(facenumber-i+1)); # permlist:=[facenumber]; permlist:=Concatenation(faceblocks); # Append(permlist,Concatenation(faceblocks)); # Add(permlist,1); pi:=PermList(permlist); nodes:=Permuted(nodes,pi); # now we have the faces in ascending order. But the second # column is still wrong. So we do some renumbering: #permlist[1]:=Size(nodes); #pi2:=PermList(permlist); for node in nodes do node[2]:=OnSets(node[2],pi); od; fi; #### # now the Hasse diagram starts with a list of points (i.e. # the faces are ordered ascendingly wrt dimension), this will work: #### Remove(nodes,1); Apply(nodes,i->Concatenation(i,[[]])); maxnode:=Size(nodes); # Remove(nodes,maxnode); for i in [1..maxnode]#-1] do # Apply(nodes[i][1],i->i+1); # if nodes[i][2]=[maxnode] # then # nodes[i][2]:=[]; # else for upface in nodes[i][2] do Add(nodes[upface-1][3],i); od; # fi; od; for node in nodes do Apply(node,Set); od; Apply(faceblocks,i->i-1); # Add(faceblocks,[maxnode]); # # And now we split the nodes of the Hasse diagram according to dimension. # This was added when the function was already complete. So this is # probably not the right order of doing things. But I didn't want to # rewrite the renumbering part above... # faceblocks:=Set(faceblocks); RemoveSet(faceblocks,[0]); for blockindex in [1..Size(faceblocks)] do nodes[blockindex]:=nodes{faceblocks[blockindex]}; od; while Size(nodes)>Size(faceblocks) do Remove(nodes); od; for blockindex in [1..Size(nodes)] do if blockindex>1 then downshift:=-faceblocks[blockindex-1][1]+1; else downshift:=0; fi; if blockindexList(n,i->i[1])), # elts:=[]); #faceindices:=Set(faceblocks)); # return returnrec; MakeImmutable(nodes); return nodes; end);hapcryst-0.2.0/examples/orbitcoloring.gap0000644000175100017510000005332315160525022020143 0ustar runnerrunner# (C)2007-2008 by Marc Roeder, # distribute under the terms of the GPL version 2.0 or later ############################################################################# ## This file provides functions to generate fundamental domains for ## 3 dimensional Bieberbach groups and view them as colored polytopes in ## JavaView. ## ## The functions you might want to use are in 3dimBieberbachFD.gap ## Look there first. ############################################################################# ############################################################################# ## ## A square root approximation using continued fractions. ## Used for the Cholesky decomposition. sqrt:=function(rat) local x,denom, num; denom:=DenominatorRat(rat); num:=NumeratorRat(rat); x:=Indeterminate(Rationals); return ContinuedFractionApproximationOfRoot(denom*x^2-num,100); end; ############################################################################# ## ## A quick and dirty implementation of a Cholesky decomposition (approximation) ## CholeskyDecomposition:=function(mat) local dim, L, line,x, col; if not mat=TransposedMat(mat) then Error("matrix is not symmetric"); fi; dim:=DimensionSquareMat(mat); if not ForAll([1..dim],d->Determinant(mat{[1..d]}{[1..d]})>0) then Error("matrix is not positive definite"); fi; L:=NullMat(dim,dim); L[1][1]:=sqrt(mat[1][1]); for line in [1..dim] do for col in [1..line-1] do if col>1 then L[line][col]:=(mat[line][col]-(L[line]{[1..col-1]}*L[col]{[1..col-1]}))/L[col][col]; else L[line][col]:=mat[line][col]/L[col][col]; fi; if line>1 then L[line][line]:=sqrt(mat[line][line]-L[line]{[1..line-1]}^2); fi; od; od; return L; end; ############################################################################# ## convert hsv color space to rgb color space. ## hsv is a triple [h,s,v] where ## h\in [0..259], s,v\in[0..255]. ## hsv2rgb:=function(hsv) local H, S, V, Hi, f, p, q, t, rgb; H:=hsv[1]; S:=1/256*hsv[2]; V:=1/256*hsv[3]; Hi:=Int(H/60) mod 6; f:=H/60-Hi; p:=V*(1-S); q:=V*(1-f*S); t:=V*(1-(1-f)*S); if Hi=0 then rgb:=[V,t,p]; elif Hi=1 then rgb:= [q,V,p]; elif Hi=2 then rgb:= [p,V,t]; elif Hi=3 then rgb:= [p,q,V]; elif Hi=4 then rgb:= [t,p,V]; elif Hi=5 then rgb:= [V,p,q]; else Error("bad programming, Marc"); fi; return List(rgb*256,Int); end; ############################################################################# ## create a list of length n which contains strings of the form ## "xxx yyy zzz" representing a point in rgb-colorspace. ## ncolorStrings:=function(n) local colorlist, Hvalues, color, rem, H, S, V; if n<=10 then colorlist:=List([0..n-1]*360/n,i->[Int(i),255,255]); else colorlist:=[]; Hvalues:=Reversed([0..Int(n/3)+1]*360/(Int(n/3)+1)); for color in [1..n] do # H:=(360/(Int(n/4)+1))*Int(color/4); rem:=(color-1) mod 3; if rem=0 then H:=Remove(Hvalues); S:=255; V:=255; elif rem=1 then S:=127; V:=255; else S:=255; V:=127; fi; Add(colorlist,[H,S,V]); od; fi; Apply(colorlist,hsv2rgb); Apply(colorlist,c->List(c,String)); Apply(colorlist,c->JoinStringsWithSeparator(c," ")); return colorlist; end; ########################## ## the same, returning a slightly paler set of colors. ## ncolorStringsPale:=function(n) local colorlist, Hvalues, color, rem, H, S, V; if n<=10 then colorlist:=List([0..n-1]*360/n,i->[Int(i),180,200]); else colorlist:=[]; Hvalues:=Reversed([0..Int(n/3)+1]*360/(Int(n/3)+1)); for color in [1..n] do # H:=(360/(Int(n/4)+1))*Int(color/4); rem:=(color-1) mod 3; if rem=0 then H:=Remove(Hvalues); S:=127; V:=255; elif rem=1 then S:=64; V:=255; else S:=127; V:=127; fi; Add(colorlist,[H,S,V]); od; fi; Apply(colorlist,hsv2rgb); Apply(colorlist,c->List(c,String)); Apply(colorlist,c->JoinStringsWithSeparator(c," ")); return colorlist; end; ############################################################################# ## Convert a rational number into a "floating point" string. ## gives the number of digits after the first non-zero ## digit after the point. ## Example with precision=3: 1/7 is converted to "0.142" ## 1/700 is converted to "0.00142" ## fraction2floatString:=function(q,precision) local sign, signString, magnitude, beforepoint, qright, prezeros, afterpoint, returnstring; if q=0 then return "0"; fi; sign:=SignRat(q); if sign=-1 then signString:="-"; else signString:=""; fi; if AbsoluteValue(q)>0 then beforepoint:=String(sign*Int(q)); qright:=sign*(q-Int(q)); else qright:=sign*q; beforepoint:="0"; fi; if qright<>0 then magnitude:=LogInt(NumeratorRat(qright),10)-LogInt(DenominatorRat(qright),10); if AbsoluteValue(qright)*10^(-magnitude)<1 then magnitude:=magnitude-1; fi; prezeros:=Concatenation(List([1..-magnitude-1],i->"0")); afterpoint:=String(Int(10^(precision-magnitude)*qright)); returnstring:=Concatenation([signString,beforepoint,".",prezeros,afterpoint]); else returnstring:=Concatenation(signString,beforepoint,".0"); fi; while returnstring[Size(returnstring)]='0' do Unbind(returnstring[Size(returnstring)]); od; if returnstring[Size(returnstring)]='.' then Unbind(returnstring[Size(returnstring)]); fi; return returnstring; end; ############################################################################# ## This converts a number to a string and fills it up with leading zeros ## if necessary. ## Example with digits=3: 5->"005" ## 1234->"1234" ## numberWithLeadingZeros:=function(n,digits) local string; string:=String(n); while Size(string)[] do vertex:=vertices[1]; orbit:=Concatenation( OrbitPartInVertexSetsStandardSpaceGroup(group,[vertex], vertices)); Add(vertexorbits,orbit); SubtractSet(vertices,orbit); od; Apply(vertexorbits,i->List(i,j->Position(vertexlist,j))); return vertexorbits; end; ################################### edgeOrbitDecomposition:=function(edges,vertexlist,group) local edgesasvectors, edgeorbits, edge, orbit; edgesasvectors:=Set(edges,i->Set(i,j->vertexlist[j])); edgeorbits:=[]; while edgesasvectors<>[] do edge:=edgesasvectors[1]; orbit:=Set(OrbitPartInVertexSetsStandardSpaceGroup(group,edge, Set(vertexlist))); SubtractSet(edgesasvectors,orbit); Add(edgeorbits,orbit); od; edgeorbits:=Set(edgeorbits); Apply(edgeorbits,i->Set(i,j->Set(j,k->Position(vertexlist,k)))); return edgeorbits; end; ############################################################################# ## Take a string and put and arund it ## enclosedByTag:=function(string,tag) return Concatenation(["<",tag,">",string,"\n"]); end; enclosedByTagNN:=function(string,tag) return Concatenation(["<",tag,">",string,""]); end; enclosedByTagWithOptions:=function(string,tag,options) return Concatenation(["<",tag," ",options,">\n",string,"\n"]); end; #################### javaviewWrappedDatastring:=function(title,abstract,detail,datastring,wrapper) local outstring, stream, line; outstring:=[]; stream:=InputTextFile(wrapper); while not IsEndOfStream(stream) do line:=ReadLine(stream); if line="##Insert Title##\n" then line:=enclosedByTag(title,"title"); Append(line,"\n"); elif line ="##Insert Abstract##\n" then line:=enclosedByTag(abstract,"abstract"); Append(line,"\n"); elif line ="##Insert Detail##\n" then line:=enclosedByTag(detail,"detail"); Append(line,"\n"); elif line="##Insert Data String##\n" then line:=enclosedByTag(datastring,"geometries"); Append(line,"\n"); else fi; Append(outstring,line); od; CloseStream(stream); return outstring; end; #################### isposdef:=function(mat) return ForAll([1..Size(mat)],d->Determinant(mat{[1..d]}{[1..d]})>0); end; ############################################################################# ## This generates the vertices for JavaView: ## The coloring is calculates separately. ############ javaviewJustPointBlock:=function(vertices,group,precision) local vector2floatString, cd, coordstrings, pstring; vector2floatString:=function(v,precision) local coordstring; coordstring:= List(v,q->fraction2floatString(q,precision)); return JoinStringsWithSeparator(coordstring," "); end; cd:=CholeskyDecomposition(GramianOfAverageScalarProductFromFiniteMatrixGroup(PointGroup(group))); coordstrings:=List(vertices,i->vector2floatString(i*cd,precision)); pstring:=Concatenation([List(coordstrings,s->enclosedByTag(s,"p")), [enclosedByTag("3","thickness")], ["\n"]]); pstring:=Concatenation(pstring); return enclosedByTag(pstring,"points"); end; javaviewPointColors:=function(vertices,group) local porbits, pcolors, pcolorlist; porbits:=vertexOrbitDecomposition(vertices,group); pcolors:=ncolorStrings(Size(porbits)); pcolorlist:=List([1..Size(vertices)],v->pcolors[PositionProperty(porbits,o->v in o)]); return enclosedByTag( Concatenation(List(pcolorlist,s->enclosedByTag(s,"c"))), "colors"); end; ############################################################################# ## And the edges ################ javaviewEdgeBlock:=function(poly,group) local int2vec, vec2int, vertices, facelattice, edges, edgeorbits, orientededges, orbit, firstedge, edge, vecedge, map, edgeimage, estring, ecolors, ecolorlist, ecstring; int2vec:=function(n) return vertices[n]; end; vec2int:=function(v) return Position(vertices,v); end; vertices:=Polymake(poly,"VERTICES"); facelattice:=Polymake(poly,"FACE_LATTICE"); edges:=Set(facelattice[Size(facelattice)-1]); edgeorbits:=edgeOrbitDecomposition(edges,vertices,group); orientededges:=[]; for orbit in edgeorbits do firstedge:=Set(orbit[1],int2vec); Add(orientededges,List(firstedge,vec2int)); for edge in orbit{[2..Size(orbit)]} do vecedge:=Set(edge,int2vec); map:=RepresentativeActionOnRightOnSets(group,firstedge,vecedge); edgeimage:=List(firstedge,v->(Concatenation(v,[1])*map)); Add(orientededges,List(edgeimage,i->vec2int(i{[1..3]}))); od; od; orientededges:=List(edges,e->First(orientededges,i->Set(i)=Set(e))); estring:=List(orientededges,e->List(e-1,String)); Apply(estring,s->JoinStringsWithSeparator(s," ")); Apply(estring,s->enclosedByTag(s,"l")); estring:=enclosedByTag( Concatenation(Concatenation(estring), enclosedByTag("4","thickness")) ,"lines"); ecolors:=ncolorStrings(Size(edgeorbits)); ecolorlist:=List(edges,v->ecolors[PositionProperty(edgeorbits,o->v in o)]); ecstring:=enclosedByTag( Concatenation(List(ecolorlist,s->enclosedByTag(s,"c"))), "colors"); return enclosedByTagWithOptions(Concatenation(["\n",estring,ecstring]), "lineSet", "line=\"show\" color=\"show\" arrow=\"show\""); end; ############################################################################# ## FACETS javaviewFacetBlock:=function(poly,group) local crossProduct, facets, facelattice, edges, ofacets, facet, facetedges, ofacet, nextvertex, nextedge, vertices, pos, v1, v2, normal, eq, testpoint, fstring, facetorbits, fcolors, fcolorlist, fcstring; crossProduct:=function(x,y) return [ x[2]*y[3]-x[3]*y[2], -(x[1]*y[3]-x[3]*y[1]), x[1]*y[2]-x[2]*y[1]]; end; Polymake(poly,"VERTICES_IN_FACETS FACE_LATTICE"); facets:=Polymake(poly,"VERTICES_IN_FACETS"); ## first, generate "ordered" versions of the facets: facelattice:=Polymake(poly,"FACE_LATTICE"); edges:=Set(facelattice[Size(facelattice)-1]); ofacets:=[]; for facet in facets do facetedges:=Set(Filtered(edges,e->IsSubset(facet,e))); ofacet:=List(facetedges[1]); RemoveSet(facetedges,ofacet); nextvertex:=ofacet[2]; while facetedges<>[] do nextedge:=First(facetedges,f->nextvertex in f); RemoveSet(facetedges,nextedge); nextvertex:=First(nextedge,i->i<>nextvertex); Add(ofacet,nextvertex); od; Remove(ofacet); Add(ofacets,ofacet); od; ## now check if the ordering must be reversed: ## We're lucky this happens in 3-space. vertices:=Polymake(poly,"VERTICES"); for pos in [1..Size(ofacets)] do v1:=vertices[ofacets[pos][2]]-vertices[ofacets[pos][1]]; v2:=vertices[ofacets[pos][3]]-vertices[ofacets[pos][1]]; normal:=crossProduct(v1,v2); eq:=Concatenation([vertices[ofacets[pos][1]]*normal],normal); testpoint:=vertices[Representative(Difference([1..Size(vertices)],ofacets[pos]))]; if WhichSideOfHyperplane(testpoint,eq)=-1 then ofacets[pos]:=Reversed(ofacets[pos]); fi; od; fstring:=List(ofacets,e->List(e-1,String)); Apply(fstring,s->JoinStringsWithSeparator(s," ")); Apply(fstring,s->enclosedByTag(s,"f")); fstring:=enclosedByTag(Concatenation(fstring) ,"faces"); facetorbits:=edgeOrbitDecomposition(facets,vertices,group); fcolors:=ncolorStringsPale(Size(facetorbits)); fcolorlist:=List(facets,v->fcolors[PositionProperty(facetorbits,o->v in o)]); fcstring:=enclosedByTag( Concatenation(List(fcolorlist,s->enclosedByTag(s,"c"))), "colors"); return enclosedByTagWithOptions(Concatenation(["\n",fstring,fcstring]), "faceSet", "face=\"show\" edge=\"show\" color=\"show\""); end; ############################################################################# ## Finally, ## generate a nice javaview file. ## It takes a number of affine matrices and generates the ## image under each of them. ########################### javaviewDatastring:=function(poly,maps,group,precision) local vertices, pstring, pcstring, edgeblock, facetblock, allgeometries, i, gshow, numberstring, m, pointblock, facetgeometry, edgegeometry; vertices:=Polymake(poly,"VERTICES"); pstring:=javaviewJustPointBlock(vertices,group,precision); pcstring:=javaviewPointColors(vertices,group); edgeblock:=javaviewEdgeBlock(poly,group); facetblock:=javaviewFacetBlock(poly,group); allgeometries:=[]; for i in [1..Size(maps)] do if i=1 then gshow:="\"show\""; if Size(maps)=1 then numberstring:=""; else numberstring:=" FD"; fi; else gshow:="\"hide\""; numberstring:=String(i-2); fi; m:=maps[i]; pstring:=javaviewJustPointBlock(List(vertices,v-> List(Concatenation(v,[1])*m){[1..3]}), group, precision); pointblock:=enclosedByTagWithOptions( Concatenation(["\n",pstring,pcstring]), "pointSet", "dim=\"3\" point=\"show\" color=\"show\" " ); facetgeometry:=enclosedByTagWithOptions( Concatenation(["\n",pointblock,"\n",facetblock,"\n"]), "geometry", Concatenation("name=\"points and facets ",numberstring,"\""," visible=",gshow) ); edgegeometry:=enclosedByTagWithOptions( Concatenation(["\n",pointblock,"\n",edgeblock,"\n"]), "geometry", Concatenation("name=\"points and edges ",numberstring,"\""," visible=",gshow) ); Append(allgeometries,Concatenation([facetgeometry,"\n",edgegeometry,"\n\n"])); od; return allgeometries; end; # ########### Here we are. The orbits are colored. # ## Now we mark a vertex for each facet to give the whole thing some # ## sort of orientation. # ## Facet normals are calculated as well. # # normals:=[]; # markingpoints:=[]; # marklines:=[]; # currentpointnr:=0; # # for facetorbit in facetorbits # do # facet:=facetorbit[1]; # facetpos:=Position(facets,facet); # v1:=vertices[ofacets[facetpos][1]]; # v2:=vertices[ofacets[facetpos][2]]; # v3:=vertices[ofacets[facetpos][3]]; # cp:=crossProduct((v2-v1)*cd,(v3-v1)*cd); # normal:=cp; # # maps:=List([1..Size(facetorbit)],i-> # RepresentativeActionOnRightOnSets(group, # Set(facet,int2vec), # Set(facetorbit[i],int2vec) # ) # ); # markedvertex:=facet[1]; # otherpointsformark:=Flat(Filtered(edges,e->markedvertex in e # and IsSubset(facet,e))); # otherpointsformark:=Filtered(Set(otherpointsformark),p->p<>markedvertex); # Apply(otherpointsformark,p->1/3*(int2vec(p)-int2vec(markedvertex))+int2vec(markedvertex)); # # # for mapnr in [1..Size(maps)] # do # map:=maps[mapnr]; # #normals first: # normalimage:=normal*LinearPartOfAffineMatOnRight(map)^cd; ## normalimage:=normalimage{[1..3]}*cd; # normalimage:=normalimage*1/sqrt(normalimage*normalimage); # facetpos:=Position(facets,facetorbit[mapnr]); # normals[facetpos]:=enclosedByTag(vector2floatString(normalimage{[1..3]},precision),"n"); # #now the marked corners: # imagepoints:=List(otherpointsformark,p->Concatenation(p,[1])*map); # Apply(imagepoints,p->p{[1..3]}*cd); # # for point in imagepoints # do # Add(markingpoints,enclosedByTag(vector2floatString(point,precision),"p")); # od; # Add(marklines,enclosedByTag(Concatenation([String(currentpointnr)," ",String(currentpointnr+1)]),"l")); # currentpointnr:=currentpointnr+2; # od; # od; # # normals:=enclosedByTag(Concatenation(normals),"normals"); # # Add(marklines,Concatenation([enclosedByTag("3","thickness"),"\n"])); # marklines:=enclosedByTag(Concatenation(marklines),"lines"); # markingpoints:=enclosedByTag(Concatenation(markingpoints),"points"); # Add(markingpoints,'\n'); # # markblock:=Concatenation( # ["\n", # enclosedByTagWithOptions(markingpoints, # "pointSet", # "dim=\"3\" point=\"hide\""), # "\n", # enclosedByTagWithOptions(marklines, # "lineSet","line=\"show\"") # ]); # ################# # # facetgeometry:=enclosedByTagWithOptions(Concatenation(["\n",pointblock,"\n",facetblock,"\n"]),"geometry","name=\"points and facets\""); # edgegeometry:=enclosedByTagWithOptions(Concatenation(["\n",pointblock,"\n",edgeblock,"\n"]),"geometry","name=\"points and edges\""); # ## markgeometry:=enclosedByTagWithOptions(markblock,"geometry","geometry=\"show\" name=\"marks\""); # # return Concatenation([facetgeometry,"\n",edgegeometry]);#,"\n",markgeometry]); #end; ############################################################################# ############################################################################# hapcryst-0.2.0/examples/javaviewwrapper.txt0000644000175100017510000000167615160525022020560 0ustar runnerrunner ##Insert Title## Marc Roeder The CHA group

National University of Ireland Galway
marc.roeder@nuigalway.ie http://hamilton.nuigalway.ie/CHA ##Insert Abstract## ##Insert Detail## Fundamental Cell Crystallographic Group HAPcryst ##Insert Data String## hapcryst-0.2.0/CHANGES.md0000644000175100017510000001412215160525022014344 0ustar runnerrunnerThis file describes changes in the AutoDoc package. ## 0.2.0 (2026-03-24) - Require GAP >= 4.12 - Require polymaking >= 0.8.6 - Change `TranslationsToBox` back to returning a list, resolve inconsistencies between its documentation and behavior. - Fix `DimensionSquareMat` to actually reject non-square matrices, and also to return `fail` instead of raising an error for bad inputs (as documented) - Fix `IsSquareMat` to not return true for *all* matrices - Various janitorial changes ## 0.1.15 (2022-07-26) - Janitorial changes ## 0.1.14 (2022-03-09) - Update some URLs in the manual ## 0.1.13 (2020-02-10) - Janitorial changes ## 0.1.12 (2020-02-02) - Add GAP Team as maintainer - Janitorial changes ## 0.1.11 (2013-10-27) - HAPcryst now calls polymaking with keywords "FACES" and "DIMS" to create a resolution of a Bieberbach group. This requires a "next generation" version of polymake. - One minor change that should reduce the number of calls to polymake by one. ## 0.1.10 (2012-04-19) - dependencies changed: AClib and Polycyclic added ## 0.1.9 (2010-06-03) - package moved to Evansville ## 0.1.8 (2008-12-02) - `IsFundamentalDomainBieberbachGroup` added - `FundamentalDomainBieberbachGroup` now tests for Bieberbachness in the non-pcp case as well. - `FundamentalDomainStandardSpaceGroup` now uses the same algorithm for all cases - HAPcryst now requires polymaking version >=0.7.6 - polymake files generated now know about their data type - Package moved from Galway to Kaiserslautern ## 0.1.7 (2008-08-13) - `TranslationOnRightFromVector` now uses a `ShallowCopy` of the given vector as the last row of the returned matrix (rather than the vector itself) - Resolutions now pretend to have length `+1`. - `FundamentalDomainBieberbach` doesn't test VOLUME any more. This is far too expensive as a standard test. - The "examples" directory is now included in the package archive and a bit more user-friendly - Test file added - Some changes in `README.HAPcryst` - HAPcryst is now a deposited package ## 0.1.6 **Changed requirements:** - HAPcryst now depends on GAP version >=4.4.10 - HAPcryst now depends on Hap - HAPcryst now suggests GAPdoc **New functionality:** - `HapLargeGroupRep` introduced - experimental framework for HAP datatypes implemented and documented. Book name: HAPprog living in `lib/datatypes/doc` - some functions to generate chain complexes from resolutions added - WhichSideOfHyperplane now has an NC version. **Changes/improvements** In `FundamentalDomainBieberbach`: - now evaluates the option `ineqThreshold`. This value triggers convex hull computations if "enough" new inequalities are known. Default is 200. - now tests the volume of the initial polyhedron. This is experimental and may be too slow as it involves calculating a triangulation via beneath-beyond. - now uses randomness. vertices are chosen in a random order to test if they can be mapped into the approximation for the fundamental domain. - now writes the inequalities for polymake in random order. This seems to improve speed. - should now be a little bit faster. (Use of `WhichSideOfHyperplaneNC`, Set->List modifications in the main procedure and newInequalities the elimination of a unnecessary polymake call) In `FaceLatticAndBoundary`: - doesn't end with a large demand for memory any more. - the hasse diagram now contains pairs [gen,groupringel] of integer `` and group ring element `` to say that the ``th entry of the boundary vector is ``. This is then turned in a vector by the boundary function. So no change in behaviour for the user. In `ResolutionFromFLandBoundary`: - the function now copies the .elts list of the face lattice, In other places: - Replaced some AddSet with Add commands in the orbit-stabilizer procedures. - `TranslationsToBox` now returns an iterator rather than a list (->RDS needed for CartesianIterator. This will probably vanish when the next GAP version is released). - `ResolutionBieberbach` now removes the temporary file it creates. - The example program now uses `FACE_LATTICE` rather than `HASSE_DIAGRAM` (output type of `HASSE_DIAGRAM` has changed in polymaking) - some functions to generate chain complexes from resolutions added - some very experimental code for contracting homotopies added (undocumented) - test file added. ## 0.1.5 - Changed bug in `FaceLatticeAndBoundary` the output is now HAP compliant again. (does not make a difference for `Homology`). - Changed `PackageInfo.g` to point to the new homepage ## 0.1.4 - Fixed an embarrassing bug in `StabilizerOnSetsStandardSpaceGroup` - introduced new methods `OrbitPartInFacesStandardSpaceGroup` and `OrbitPartAndRepresentativesInFacesStandardSpaceGroup` - `FaceLatticeAndBoundaryBieberbachGroup` is now a good deal faster in some hard cases. - removed unused variable `HAPCRYST_TMPDIR`. `POLYMAKE_DATA_DIR` should do the job. - corrected a few errors in the manual - README written (thanks to David Joyner). ## 0.1.3 - Changed package dependencies (Cryst >=4.1.5) - Added description for PointGroupRepresentatives to manual. ## 0.1.2 Changes affecting behaviour of HAPcryst: - Removed `LatticeTransAndPointGroupRepsOnRight`. - Added `PointGroupRepresentatives` (attribute) - Fixed a bug in `FundamentalDomainBieberbachGroup` which could lead to wrong results in the non-standard case. - Fixed a minor bug in `FundamentalDomainAffineCrystGroupOnRight` which could lead to calculating "fundamental domains" in cases where this is not possible... - Added `StabilizerOnSetsStandardSpaceGroup` - Added `IsFundamentalDomainStandardSpaceGroup` - All `OrbitStabilizer` algorithms now return the stabilizer rather than just generators. - `FundamentalDomainBieberbachGroup` now checks if a group is Bieberbach or outputs a line of information, if no check is performed. Minor changes: - Added LICENSE.txt. - Added "examples" directory. This currently contains a program to calculate colored fundamental domains of 3-dimensional Bieberbach groups. - Some changes in documentation ## 0.1.1 - First version as a package.