def compute_xsi(self, u): r""" EXAMPLES:: sage: from slabbe.word_morphisms import compute_xsi sage: s = WordMorphism({0:[0,1],1:[1,0]}) sage: compute_xsi(s, Word([0])) sigma_u= 0->012, 1->02, 2->1 theta_u= 0->011, 1->01, 2->0 psi= 0->(0, 0),(0, 1),(0, 2), 1->(1, 0),(1, 1), 2->(2, 0) psi*sigma_u= 0->(0, 0),(0, 1),(0, 2),(1, 0),(1, 1),(2, 0), 1->(0, 0),(0, 1),(0, 2),(2, 0), 2->(1, 0),(1, 1) Finite words over {(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (2, 0)} [1 0 0] [1 0 0] [1 0 0] [0 1 0] [0 1 0] [0 0 1] We want zeta such that: zeta((0, 0),(0, 1),(0, 2)) = (0, 0),(0, 1),(0, 2),(1, 0),(1, 1),(2, 0) zeta((1, 0),(1, 1)) = (0, 0),(0, 1),(0, 2),(2, 0) zeta((2, 0)) = (1, 0),(1, 1) """ sigma_u, theta_u = return_substitution(self, u, coding=True) assert theta_u * sigma_u == self * theta_u, "identity is not verified" print "sigma_u=", sigma_u print "theta_u=", theta_u d = { k: [(k, i) for i in range(len(v))] for k, v in theta_u._morph.iteritems() } psi = WordMorphism(d) print "psi=", psi print "psi*sigma_u=", psi * sigma_u print psi.codomain() print psi.incidence_matrix() print "We want zeta such that:" for k, v in psi._morph.iteritems(): print "zeta({}) = {}".format(v, psi(sigma_u(k)))
def compute_xsi(self, u): r""" EXAMPLES:: sage: from slabbe.word_morphisms import compute_xsi sage: s = WordMorphism({0:[0,1],1:[1,0]}) sage: compute_xsi(s, Word([0])) sigma_u= 0->012, 1->02, 2->1 theta_u= 0->011, 1->01, 2->0 psi= 0->(0, 0),(0, 1),(0, 2), 1->(1, 0),(1, 1), 2->(2, 0) psi*sigma_u= 0->(0, 0),(0, 1),(0, 2),(1, 0),(1, 1),(2, 0), 1->(0, 0),(0, 1),(0, 2),(2, 0), 2->(1, 0),(1, 1) Finite words over {(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (2, 0)} [1 0 0] [1 0 0] [1 0 0] [0 1 0] [0 1 0] [0 0 1] We want zeta such that: zeta((0, 0),(0, 1),(0, 2)) = (0, 0),(0, 1),(0, 2),(1, 0),(1, 1),(2, 0) zeta((1, 0),(1, 1)) = (0, 0),(0, 1),(0, 2),(2, 0) zeta((2, 0)) = (1, 0),(1, 1) """ sigma_u, theta_u = return_substitution(self, u, coding=True) assert theta_u*sigma_u == self*theta_u, "identity is not verified" print("sigma_u=", sigma_u) print("theta_u=", theta_u) d = {k:[(k,i) for i in range(len(v))] for k,v in theta_u._morph.iteritems()} psi = WordMorphism(d) print("psi=", psi) print("psi*sigma_u=", psi*sigma_u) print(psi.codomain()) print(psi.incidence_matrix()) print("We want zeta such that:") for k,v in psi._morph.iteritems(): print("zeta({}) = {}".format(v, psi(sigma_u(k))))
class GeoSub(SageObject): r""" INPUT: - ``sigma`` -- dict, substitution - ``k`` -- integer - ``presuf`` -- string (default: ``"prefix"``), ``"prefix"`` or ``"suffix"`` - ``dual`` -- bool (default: ``False``) EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: E = GeoSub(sub, 2) sage: E E_2(1->12, 2->13, 3->1) """ def __init__(self, sigma, k, presuf='prefix', dual=False): self._sigma_dict = sigma self._sigma = WordMorphism(sigma) self._k = k if not presuf in ['prefix', 'suffix']: raise ValueError('Input presuf(={}) should be "prefix" or' ' "suffix"'.format(presuf)) self._presuf = presuf self._dual = dual def is_dual(self): return self._dual @cached_method def field(self): r""" EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: E = GeoSub(sub,2) sage: E.field() Number Field in b with defining polynomial x^3 - x^2 - x - 1 """ M = self._sigma.incidence_matrix() b1 = max(M.eigenvalues(), key=abs) f = b1.minpoly() K = NumberField(f, 'b') return K def gen(self): r""" EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: E = GeoSub(sub,2) sage: E.gen() b^2 - b - 1 """ b = self.field().gen() if self.is_dual(): return b else: return b**-1 def dominant_left_eigenvector(self): r""" EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: E = GeoSub(sub,2) sage: E.dominant_left_eigenvector() (1, b - 1, b^2 - b - 1) """ M = self._sigma.incidence_matrix() - self.field().gen() return M.left_kernel().basis()[0] def dominant_right_eigenvector(self): r""" EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: E = GeoSub(sub,2) sage: E.dominant_right_eigenvector() (1, b^2 - b - 1, -b^2 + 2*b) """ M = self._sigma.incidence_matrix() - self.field().gen() return M.right_kernel().basis()[0] def complex_embeddings(self): r""" EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: E = GeoSub(sub,2) sage: E.complex_embeddings() [-0.419643377607081 - 0.606290729207199*I, -0.419643377607081 + 0.606290729207199*I, 1.83928675521416] """ return self.field().gen().complex_embeddings() def contracting_eigenvalues_indices(self): r""" EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: E = GeoSub(sub,2) sage: E.contracting_eigenvalues_indices() [0, 1] """ L = self.complex_embeddings() return [L.index(x) for x in L if abs(x) < 1] def dilating_eigenvalues_indices(self): r""" EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: E = GeoSub(sub,2) sage: E.dilating_eigenvalues_indices() [2] """ L = self.complex_embeddings() return [L.index(x) for x in L if abs(x) > 1] def minkowski_embedding_with_left_eigenvector(self): r""" EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: E = GeoSub(sub,2) sage: E.minkowski_embedding_with_left_eigenvector() [ -1.00000000000000 -0.839286755214161 -0.543689012692076] [ -1.00000000000000 1.41964337760708 0.771844506346038] [ 0.000000000000000 -0.606290729207199 1.11514250803994] :: sage: E = GeoSub(sub, 2, dual=True) sage: E.minkowski_embedding_with_left_eigenvector() [ 1.00000000000000 0.839286755214161 0.543689012692076] [ 1.00000000000000 -1.41964337760708 -0.771844506346038] [ 0.000000000000000 0.606290729207199 -1.11514250803994] """ K = self.field() if self.is_dual(): vb = self.dominant_left_eigenvector() else: vb = -self.dominant_left_eigenvector() return Minkowski_embedding_without_sqrt2(K, vb) def projection(self): r""" EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: GeoSub(sub, 2).projection() [ -1.000000000000000000000000000000 -0.8392867552141611325518525646713 -0.5436890126920763615708559718500] sage: GeoSub(sub, 2, dual=True).projection() [ 1.00000000000000 -1.41964337760708 -0.771844506346038] [ 0.000000000000000 0.606290729207199 -1.11514250803994] """ K = self.field() vb = self.dominant_left_eigenvector() P, Q = Minkowski_projection_pair(K, vb) if self.is_dual(): return Q else: return -P @cached_method def base_iter(self): r""" EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: E = GeoSub(sub,2) sage: E.base_iter() {(1, 2): [[(0, 0, 0), (1,)], [(1, 0, 0), (2,)], [(0, 0, 0), (1, 1)], [(1, 0, 0), (1, 3)], [(1, 0, 0), (2, 1)], [(2, 0, 0), (2, 3)]], (1, 3): [[(0, 0, 0), (1,)], [(1, 0, 0), (2,)], [(0, 0, 0), (1, 1)], [(1, 0, 0), (2, 1)]], (2, 3): [[(0, 0, 0), (1,)], [(1, 0, 0), (3,)], [(0, 0, 0), (1, 1)], [(1, 0, 0), (3, 1)]]} """ X = {} S = self._sigma_dict.keys() for x in combinations(S, self._k): X[x] = [] bigL = [] for y in x: if self.is_dual(): bigL.append( ps_automaton_inverted(self._sigma_dict, self._presuf)[y]) else: bigL.append( ps_automaton(self._sigma_dict, self._presuf)[y]) Lpro = list(product(*bigL)) for el in Lpro: z = [] w = [] for i in range(len(el)): z += el[i][1] w.append(el[i][0]) if self.is_dual(): M = self._sigma.incidence_matrix() X[x].append([-M.inverse() * abelian(z, S), tuple(w)]) else: X[x].append([abelian(z, S), tuple(w)]) return X def __call__(self, patch, iterations=1): r""" EXAMPLES:: sage: from EkEkstar import GeoSub, kPatch, kFace sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: geosub = GeoSub(sub,2, 'prefix',1) sage: P = kPatch([kFace((0,0,0),(1,2),dual=True), ....: kFace((0,0,1),(1,3),dual=True), ....: kFace((0,1,0),(2,1),dual=True), ....: kFace((0,0,0),(3,1),dual=True)]) sage: Q = geosub(P, 6) sage: Q Patch of 47 faces """ if iterations == 0: return kPatch(patch) elif iterations < 0: raise ValueError("iterations (=%s) must be >= 0." % iterations) else: old_faces = patch for i in range(iterations): new_faces = kPatch([]) for f, m in old_faces: new_faces += m * kPatch( self._call_on_face(f, color=f.color())) old_faces = new_faces return new_faces def matrix(self): r""" EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: E = GeoSub(sub,2) sage: E.matrix() [1 1 1] [1 0 0] [0 1 0] """ if self.is_dual(): return self._sigma.incidence_matrix().inverse() else: return self._sigma.incidence_matrix() def _call_on_face(self, face, color=None): r""" INPUT: - ``face`` -- a face - ``color`` -- a color or None OUTPUT: dict of the form ``{face:multiplicity for face in faces}`` EXAMPLES:: sage: from EkEkstar import GeoSub, kFace sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: E = GeoSub(sub,2) The available face type are:: sage: E.base_iter().keys() [(1, 2), (1, 3), (2, 3)] For each we get:: sage: d = E._call_on_face(kFace((10,11,12), (1,2))) sage: sorted(d.items()) [([(34, 10, 11), (1, 3)], 1), ([(33, 10, 11), (1, 1)], 1), ([(34, 10, 11), (2, 1)], 1), ([(35, 10, 11), (2, 3)], 1)] sage: sorted(E._call_on_face(kFace((10,11,12), (1,3))).items()) [([(34, 10, 11), (2, 1)], 1), ([(33, 10, 11), (1, 1)], 1)] sage: E._call_on_face(kFace((10,11,12), (2,3))) {[(33, 10, 11), (1, 1)]: 1, [(34, 10, 11), (3, 1)]: 1} """ x_new = self.matrix() * face.vector() #t = face.type() t = face.sorted_type() if self.is_dual(): return { kFace(x_new - vv, tt, dual=self.is_dual()): (-1)**(sum(t) + sum(tt)) * face.sign() for (vv, tt) in self.base_iter()[t] if len(tt) == self._k } else: return { kFace(x_new + vv, tt, dual=self.is_dual()): face.sign() for (vv, tt) in self.base_iter()[t] if len(tt) == self._k } def __repr__(self): r""" EXAMPLES:: sage: from EkEkstar import GeoSub sage: sub = {1:[1,2], 2:[1,3], 3:[1]} sage: GeoSub(sub, 2) E_2(1->12, 2->13, 3->1) sage: GeoSub(sub, 2, dual=True) E*_2(1->12, 2->13, 3->1) """ if self.is_dual(): return "E*_%s(%s)" % (self._k, str(self._sigma)) else: return "E_%s(%s)" % (self._k, str(self._sigma))