Source code for geometry.similarity_surface_generators

from sage.rings.integer_ring import ZZ
from sage.misc.cachefunc import cached_method

ZZ_1 = ZZ(1)
ZZ_2 = ZZ(2)

from similarity_surface import TranslationSurface_generic

[docs]class InfiniteStaircase(TranslationSurface_generic): r""" The infinite staircase. ... +--+--+ | | | +--+--+--+ | | | +--+--+--+ | | | +--+--+--+ | | | +--+--+ ... """ def _repr_(self): r""" String representation. """ return "The infinite staircase"
[docs] def base_ring(self): r""" Return the rational field. """ from sage.rings.rational_field import QQ return QQ
[docs] def polygon(self, lab): r""" Return the polygon labeled by ``lab``. """ if lab not in self.polygon_labels(): raise ValueError("lab (=%s) not a valid label"%lab) from geometry.polygon import square return square()
[docs] def polygon_labels(self): r""" The set of labels used for the polygons. """ return ZZ
[docs] def opposite_edge(self, p, e): r""" Return the pair ``(pp,ee)`` to which the edge ``(p,e)`` is glued to. """ if (p+e) % 2: return p+1,(e+2)%4 else: return p-1,(e+2)%4
[docs]class EInfinity(TranslationSurface_generic): r""" The surface based on the $E_\infinity$ graph. The biparite graph is shown below, with edges numbered: 0 1 2 -2 3 -3 4 -4 *---o---*---o---*---o---*---o---*... | |-1 o Here, black vertices are colored *, and white o. Black nodes represent vertical cylinders and white nodes represent horizontal cylinders. """ def __init__(self,lambda_squared=None, field=None): TranslationSurface_generic.__init__(self) if lambda_squared==None: from sage.rings.number_field.number_field import NumberField from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing R=PolynomialRing(ZZ,'x') x = R.gen() from sage.rings.qqbar import AA self._field=NumberField(x**3-ZZ(5)*x**2+ZZ(4)*x-ZZ(1), 'r', embedding=AA(ZZ(4))) self._l=self._field.gen() else: if field is None: self._l=lambda_squared self._field=lambda_squared.parent() else: self._field=field self._l=field(lambda_squared) def _repr_(self): r""" String representation. """ return "The E-infinity surface"
[docs] def base_ring(self): r""" Return the rational field. """ return self._field
@cached_method
[docs] def get_white(self,n): r"""Get the weight of the white endpoint of edge n.""" l=self._l if n==0 or n==1: return l if n==-1: return l-1 if n==2: return 1-3*l+l**2 if n>2: x=self.get_white(n-1) y=self.get_black(n) return l*y-x return self.get_white(-n)
@cached_method
[docs] def get_black(self,n): r"""Get the weight of the black endpoint of edge n.""" l=self._l if n==0: return self._field(1) if n==1 or n==-1 or n==2: return l-1 if n>2: x=self.get_black(n-1) y=self.get_white(n-1) return y-x return self.get_black(1-n)
[docs] def polygon(self, lab): r""" Return the polygon labeled by ``lab``. """ if lab not in self.polygon_labels(): raise ValueError("lab (=%s) not a valid label"%lab) from geometry.polygon import rectangle return rectangle(2*self.get_black(lab),self.get_white(lab))
[docs] def polygon_labels(self): r""" The set of labels used for the polygons. """ return ZZ
[docs] def opposite_edge(self, p, e): r""" Return the pair ``(pp,ee)`` to which the edge ``(p,e)`` is glued to. """ if p==0: if e==0: return (0,2) if e==1: return (1,3) if e==2: return (0,0) if e==3: return (1,1) if p==1: if e==0: return (-1,2) if e==1: return (0,3) if e==2: return (2,0) if e==3: return (0,1) if p==-1: if e==0: return (2,2) if e==1: return (-1,3) if e==2: return (1,0) if e==3: return (-1,1) if p==2: if e==0: return (1,2) if e==1: return (-2,3) if e==2: return (-1,0) if e==3: return (-2,1) if p>2: if e%2: return -p,(e+2)%4 else: return 1-p,(e+2)%4 else: if e%2: return -p,(e+2)%4 else: return 1-p,(e+2)%4
[docs]class TFractal(TranslationSurface_generic): r""" The TFractal surface. The TFractal surface is a translation surface of finite area built from infinitely many polygons. The basic building block is the following polygon w/r w w/r +---+------+---+ | 1 | 2 | 3 | h2 +---+------+---+ | 0 | h1 +------+ w where ``w``, ``h1``, ``h2``, ``r`` are some positive numbers. Default values are ``w=h1=h2=1`` and ``r=2``. .. TODO:: In that surface, the linear flow can be computed more efficiently using only one affine interval exchange transformation with 5 intervals. But the underlying geometric construction is not a covering. Warning: we can not play at the same time with tuples and element of a cartesian product (see Sage trac ticket #19555) """ def __init__(self, w=ZZ_1, r=ZZ_2, h1=ZZ_1, h2=ZZ_1): from sage.structure.sequence import Sequence from sage.combinat.words.words import Words self._field = Sequence([w,r,h1,h2]).universe() if not self._field.is_field(): self._field = self._field.fraction_field() self._w = self._field(w) self._r = self._field(r) self._h1 = self._field(h1) self._h2 = self._field(h2) self._words = Words('LR', finite=True, infinite=False) self._wL = self._words('L') self._wR = self._words('R') def _repr_(self): return "The T-fractal surface with parameters w=%s, r=%s, h1=%s, h2=%s"%( self._w, self._r, self._h1, self._h2)
[docs] def base_ring(self): return self._field
@cached_method
[docs] def polygon_labels(self): from sage.sets.finite_enumerated_set import FiniteEnumeratedSet from sage.categories.cartesian_product import cartesian_product return cartesian_product([self._words, FiniteEnumeratedSet([0,1,2,3])])
[docs] def opposite_edge(self, p, e): r""" Labeling of polygons wl,0 wr,0 +-----+---------+------+ | | | | | w,1 | w,2 | w,3 | | | | | +-----+---------+------+ | | | w,0 | | | +---------+ w and we always have: bot->0, right->1, top->2, left->3 EXAMPLES:: sage: T = TFractal() sage: W = T._words sage: w = W('LLRLRL') sage: T.opposite_edge((w,0),0) ((word: LLRLR, 1), 2) sage: T.opposite_edge((w,0),1) ((word: LLRLRL, 0), 3) sage: T.opposite_edge((w,0),2) ((word: LLRLRL, 2), 0) sage: T.opposite_edge((w,0),3) ((word: LLRLRL, 0), 1) """ w,i = p w = self._words(w) i = int(i) e = int(e) if e==0: f=2 elif e==1: f=3 elif e==2: f=0 elif e==3: f=1 else: raise ValueError("e (={!r}) must be either 0,1,2 or 3".format(e)) if i == 0: if e == 0: if w.is_empty(): lab=(w,2) elif w[-1] == 'L': lab=(w[:-1],1) elif w[-1] == 'R': lab=(w[:-1],3) if e == 1: lab=(w,0) if e == 2: lab=(w,2) if e == 3: lab=(w,0) elif i == 1: if e == 0: lab=(w + self._wL, 2) if e == 1: lab=(w,2) if e == 2: lab=(w + self._wL, 0) if e == 3: lab=(w,3) elif i == 2: if e == 0: lab=(w,0) if e == 1: lab=(w,3) if e == 2: if w.is_empty(): lab=(w,0) elif w[-1] == 'L': lab=(w[:-1],1) elif w[-1] == 'R': lab=(w[:-1],3) if e == 3: lab=(w,1) elif i == 3: if e == 0: lab=(w + self._wR, 2) if e == 1: lab=(w,1) if e == 2: lab=(w + self._wR, 0) if e == 3: lab=(w,2) else: raise ValueError("i (={!r}) must be either 0,1,2 or 3".format(i)) # the fastest label constructor lab = self.polygon_labels()._cartesian_product_of_elements(lab) return lab,f
[docs] def polygon(self, lab): r""" Return the polygon with label ``lab``. w/r w/r +---+------+---+ | 1 | 2 | 3 | | | | | h2 +---+------+---+ | 0 | h1 +------+ w EXAMPLES:: sage: T.polygon(('L',0)) Polygon: (0, 0), (1/2, 0), (1/2, 1/2), (0, 1/2) sage: T.polygon(('LRL',0)) Polygon: (0, 0), (1/8, 0), (1/8, 1/8), (0, 1/8) """ w = self._words(lab[0]) return (1 / self._r ** w.length()) * self._base_polygon(lab[1])
@cached_method def _base_polygon(self, i): from geometry.polygon import Polygons if i == 0: w = self._w h = self._h1 if i == 1 or i == 3: w = self._w / self._r h = self._h2 if i == 2: w = self._w h = self._h2 return Polygons(self.base_ring())([(w,0),(0,h),(-w,0),(0,-h)])
[docs] def base_label(self): return self.polygon_labels()._cartesian_product_of_elements((self._words(''), 0))
[docs]class SimilaritySurfaceGenerators: r""" Examples of similarity surfaces. """ @staticmethod
[docs] def example(): r""" Construct a SimilaritySurface from a pair of triangles. """ from geometry.similarity_surface import SimilaritySurface_polygons_and_gluings from geometry.polygon import PolygonCreator pc=PolygonCreator() pc.add_vertex((0,0)) pc.add_vertex((2,-2)) pc.add_vertex((2,0)) p0=pc.get_polygon() pc=PolygonCreator() pc.add_vertex((0,0)) pc.add_vertex((2,0)) pc.add_vertex((1,3)) p1=pc.get_polygon() ps=(p0,p1) glue={ (0,2):(1,0), (0,0):(1,1), (0,1):(1,2), (1,0):(0,2), (1,1):(0,0), (1,2):(0,1) } return SimilaritySurface_polygons_and_gluings(ps,glue)
@staticmethod
[docs] def right_angle_triangle(w,h): from sage.structure.sequence import Sequence from geometry.polygon import Polygons from sage.modules.free_module import VectorSpace from geometry.similarity_surface import SimilaritySurface_polygons_and_gluings F = Sequence([w,h]).universe() if not F.is_field(): F = F.fraction_field() V = VectorSpace(F,2) P1 = Polygons(F)([V((w,0)),V((-w,h)),V((0,-h))]) P2 = Polygons(F)([V((0,h)),V((-w,-h)),V((w,0))]) ps = (P1,P2) glue = {(0,0):(1,2),(0,1):(1,1),(0,2):(1,0)} return SimilaritySurface_polygons_and_gluings(ps,glue)
[docs]class TranslationSurfaceGenerators: r""" Common and less common translation surfaces. """ @staticmethod
[docs] def regular_octagon(): r""" Return the translation surface built from the regular octagon by identifying opposite sides. EXAMPLES:: sage: T = translation_surfaces.regular_octagon() sage: T Translation surface built from the regular octagon sage: T.stratum() H_2(2) """ from geometry.polygon import regular_octagon from geometry.similarity_surface import TranslationSurface_polygons_and_gluings polygons = [regular_octagon()] identifications = {} identifications.update(dict(((0,i),(0,i+4)) for i in xrange(4))) return TranslationSurface_polygons_and_gluings(polygons=polygons, identifications=identifications)
@staticmethod
[docs] def octagon_and_squares(): from geometry.polygon import square, regular_octagon from sage.matrix.matrix_space import MatrixSpace from geometry.similarity_surface import TranslationSurface_polygons_and_gluings o = regular_octagon() K = o.parent().field() sqrt2 = K.gen() rot = MatrixSpace(K,2)([[sqrt2/ZZ_2,-sqrt2/ZZ_2],[sqrt2/ZZ_2,sqrt2/ZZ_2]]) polygons = [regular_octagon(), ZZ_2*square(K), ZZ_2*rot*square(K)] identifications = { (0,0): (1,3), (0,1): (2,3), (0,2): (1,0), (0,3): (2,0), (0,4): (1,1), (0,5): (2,1), (0,6): (1,2), (0,7): (2,2), } return TranslationSurface_polygons_and_gluings(polygons=polygons, identifications=identifications)
@staticmethod
[docs] def origami(r,u,rr=None,uu=None,domain=None): r""" Return the origami defined by the permutations ``r`` and ``u``. EXAMPLES:: sage: S = SymmetricGroup(3) sage: r = S('(1,2)') sage: u = S('(1,3)') sage: o = translation_surfaces.origami(r,u) sage: o Origami defined by r=(1,2) and u=(1,3) sage: o.stratum() H_2(2) """ from geometry.similarity_surface import Origami return Origami(r,u,rr,uu,domain)
@staticmethod
[docs] def infinite_staircase1(): return InfiniteStaircase()
@staticmethod
[docs] def infinite_staircase2(): from geometry.similarity_surface import Origami return Origami( lambda x: x+1 if x%2 else x-1, # r (edge 1) lambda x: x-1 if x%2 else x+1, # u (edge 2) lambda x: x+1 if x%2 else x-1, # rr (edge 3) lambda x: x-1 if x%2 else x+1, # uu (edge 0) domain = ZZ)
@staticmethod
[docs] def t_fractal(w=ZZ_1, r=ZZ_2, h1=ZZ_1, h2=ZZ_1): return TFractal(w,r,h1,h2)