def __init__(self, cvs=None, z_center=1j, scale=5.0, bg=white): self.g_center = Mobius.cayley(z_center) * ~Mobius.cayley() if cvs is None: cvs = Canvas() cvs.append(Scale(scale)) if bg is not None: cvs.fill(path.rect(-1, -1, 2, 2), [bg]) self.cvs = cvs
def _construct_short(cls, z0, z1): g = Mobius.get_translate(z0, z1) l, r = g.fixed() src, tgt = l, r theta0 = get_angle(src) theta1 = get_angle(tgt) r_cos = 1 / cos(0.5 * abs(theta0 - theta1)) radius = tan(0.5 * abs(theta0 - theta1)) z_center = r_cos * cmath.exp(1j * 0.5 * (theta0 + theta1)) if radius < 0: radius = -radius theta0 = get_angle(z0 - z_center) % (2 * pi) theta1 = get_angle(z1 - z_center) % (2 * pi) theta2 = 0.5 * (theta0 + theta1) z2 = z_center + radius * cmath.exp(1j * theta2) meths = [path.arc, path.arcn] idx = 0 if theta0 > theta1: idx = 1 #print(theta1-theta0) if abs(theta1 - theta0) > pi: theta1 = theta1 - 2 * pi idx = 1 - idx gamma = CircleGeodesic(z_center, radius, theta0, theta1, meths[idx]) assert abs(gamma.z0 - z0) < EPSILON, (gamma.z0, z0) assert abs(gamma.z1 - z1) < EPSILON, (gamma.z1, z1) return gamma
def main_poincare_1(): for (l, m, n, maxsize) in [(5, 2, 4, 4000)]: # build the rotation group generators a, b = [g.todisc() for g in mktriangle(l, m, n)] cvs = Canvas() cvs.append(Scale(2.)) disc = Disc(cvs) z_face = 0j z_vert = (a * b).inner_fixed() gamma = Geodesic.construct(z_vert, (~a)(z_vert)) z_edge = gamma.z2 # midpoint g_face = gamma.get_refl() gamma = Geodesic.construct(z_face, z_vert) g_edge = gamma.get_refl() g_vert = Mobius.conjugate() gens = [g_face, g_edge, g_vert] gens = gens + [~g for g in gens] G = mulclose(gens, verbose=True, maxsize=maxsize) faces, edges, verts = [], [], [] for g in G: faces.append(g(z_face)) edges.append(g(z_edge)) verts.append(g(z_vert)) for g in G: disc.show_geodesic(g(z_face), g(z_vert), attrs=st_round + [grey.alpha(0.1)]) for g in G: disc.show_geodesic(g(z_face), g(z_edge), attrs=st_round + [grey]) for g in G: disc.show_geodesic(g(z_vert), g(z_edge), attrs=st_round) # for [cl, zs] in ([green, faces], [blue, edges], [red, verts]): for [cl, zs] in ([red, verts], ): for z in zs: disc.show_point(z, [cl]) disc.fini() disc.save("poincare-rotation-%d%d%d" % (l, m, n))
def main_bring(): global cvs gens = [Mobius(1, 1, 0, 1), Mobius(0, 1, -1, 0)] gens = [Mobius(1, 2, 0, 1), Mobius(1, 0, -2, 1)] gens = mktriangle(5, 2, 5) a, b = gens z1 = (a * b).inner_fixed() # pentagon center gens = [g.todisc() for g in gens] # --------------- todisc -------------- I = Mobius() cvs = Canvas([Scale(5)]) disc = Disc(cvs, z1) a, b = gens ab = a * b c = ab ci = ~c assert (ci * ci * a).order() == 5 assert ab.order() == 5 z0 = a.inner_fixed() z1 = c.inner_fixed() # pentagon center z2 = b.inner_fixed() # edge center z3 = b(z0) # other end of an edge #G = mulclose(gens, maxsize=2000) #G = [Mobius(), a, b, a*b, b*a] G = [ab**idx for idx in range(5)] # cvs.paint([white]) # broken ?!? aspect = 16 / 9 h = 2.2 w = aspect * h #cvs.fill(path.rect(-0.5*w, -0.5*h, w, h), [white]) p = path.circle(0, 0, 1) #cvs.fill(p, [grey]) #cvs.clip(p) #cvs.stroke(p) #G = mulclose([a, b, ~a, ~b], g0=~disc.g_center, maxsize=2000) G = mulclose([a, b], maxsize=800) # 8000 is good op = ~disc.g_center #G = [op * g for g in G] bring = [I] #disc.show_fixed(a) edges = [] for conj in [I, c, c * c, c * c * c, c * c * c * c]: b1 = conj * b * ~conj a1 = conj * a * ~conj #disc.show_fixed(a1) # _vertices #disc.show_fixed(b1) # edge midpoints z = b1.inner_fixed() edges.append(z) tx0, tx1 = (a1 * a1 * b1)**3, (a1 * b1 * a1)**3 #bring += [tx0, ~tx0, tx1, ~tx1] def shrink(pts, center=None, alpha=0.07): if center is None: center = sum(pts) / len(pts) pts = [conv(alpha, z, center) for z in pts] return pts star = [] for i in range(5): g = a**i star.append(g(edges[0])) #star = shrink(star, z0) #disc.show_polygon(star, [green]+st_round, [green.alpha(0.5)]) edges = shrink(edges, z1) star = shrink(star, z0) def get_translates(w): found = [] for g in G: if not g.is_translate(): continue for z in found: if abs(z - g(w)) < EPSILON: break else: yield g z = g(w) found.append(z) def show_sigma(): g = a * ci * ci * a src, tgt = g.fixed() for i in range(5): op = ci**i disc.show_geodesic(op(src), op(tgt), [orange.alpha(0.4)]) break #print(src) src = disc.g_center(src) #disc.show_point(src) x, y = src.real, src.imag #cvs.stroke(path.circle(x, y, 0.1)) z = src * 1j dx, dy = 0.2 * z.real, 0.2 * z.imag cvs.text(x + 0.2, y - 0.1, r"$\sigma$", [Scale(0.5)] + st_center) r = 1.12 cvs.stroke(path.line(x, y, r * x, r * y), [orange.alpha(0.4)]) x, y = 1.1 * x, 1.1 * y st = [deco.earrow(size=0.1)] + [0.7 * thin] cvs.stroke(path.line(x, y, x + dx, y + dy), st) cvs.stroke(path.line(x, y, x - dx, y - dy), st) def show_faces(min_lw=0.00): for g in get_translates(z1): z = g(z1) lw = 4. / disc.d_poincare(z) if lw < min_lw: break pts = [g(v) for v in edges] disc.show_polygon(pts, [lw * thin, green] + st_round, [green.alpha(0.3)]) #disc.show_point(z0) for g in get_translates(z0): z = g(z0) lw = 4. / disc.d_poincare(z) if lw < min_lw: break pts = [g(v) for v in star] disc.show_polygon(pts, [lw * thin, blue] + st_round, [blue.alpha(0.3)]) #bring = [I] #G0 = mulclose([a, b], maxsize=20) #bring += [g*tx0*~g for g in G0] #bring += [g*tx1*~g for g in G0] #for op in bring[1:]: # #disc.show_fixed(op) # src, tgt = (op).fixed() # disc.show_geodesic(src, tgt, [green.alpha(0.5)]) #bring = [I, tx0*~tx1*tx0] #bring = mulclose([tx0, tx1, ~tx0, ~tx1], maxsize=20) #disc.show_fixed(bring[0]) #bring = mulclose(bring, maxsize=200) def show_bring(): tiles = [ ( 1, I, ), ( 2, (c**3) * a, ), ( 3, (c**2) * a, ), ( 4, c * a, ), ( 5, a, ), ( 6, (c**4) * a, ), ( 7, a**2, ), ( 8, a**3, ), ( 9, ci * a**2, ), ( 10, ci * a**3, ), ( 11, ci**2 * a**2, ), (7, ci**2 * a**3), ( 8, ci**3 * a**2, ), (9, ci**3 * a**3), ( 10, ci**4 * a**2, ), (11, ci**4 * a**3), ] #g = ci*a**2 #h = ci**3*a**3 #disc.show_fixed(h*~g) #bring = [I, h*~g] g = a**3 * b * a**-3 a1 = g * a * ~g #disc.show_fixed(a1*a1) #assert a1.order() == 5, a1.order() tiles.append((11, a1**2 * a**3)) tiles.append((9, a1**4 * a**3)) for (count, g) in tiles: #if count == 5: # g = (tx0**-3)*g for h in bring: g2 = disc.g_center * h * g z = g2(z1) ds = 1. / d_poincare(z)**0.7 if ds > 0.05: cvs.text(z.real, z.imag, str(count), [Scale(ds)] + st_center) #break #show_sigma() #show_faces() show_bring() disc.show_tiles(G) p = path.circle(0, 0, 1) cvs.clip(p) cvs.stroke(p, [1.0 * thin]) #save("hyperbolic-55") #save("fold-hyperbolic-55") save("brings-curve") print("OK") print()
def render_group(l, m, n, words=[], rels=[], labels={}, name="output", maxsize=1000): # build the rotation group generators a, b = [g.todisc() for g in mktriangle(l, m, n)] assert (a.order()) == 10 # SL(2) not PSL(2) assert (b.order()) == 4 # SL(2) not PSL(2) c = (~b) * (~a) cvs = Canvas() cvs.append(Scale(4.)) disc = Disc(cvs) z_face = 0j z_vert = (a * b).inner_fixed() gamma = Geodesic.construct(z_vert, (~a)(z_vert)) z_edge = gamma.z2 # midpoint #z_tile = (1/3)*(z_face + z_edge + z_vert) z_tile = (1 / 2) * (z_face + z_vert) g_face = gamma.get_refl() gamma = Geodesic.construct(z_face, z_vert) g_edge = gamma.get_refl() g_vert = Mobius.conjugate() gens = [g_vert, ~g_vert, g_edge, ~g_edge, g_face, ~g_face] G = mulclose(gens, verbose=True, maxsize=maxsize) faces, edges, verts = [], [], [] for g in G: faces.append(g(z_face)) edges.append(g(z_edge)) verts.append(g(z_vert)) #for g in G: # disc.show_geodesic(g(z_face), g(z_vert), attrs=st_round+[grey.alpha(0.1)]) for g in G: disc.show_geodesic(g(z_face), g(z_edge), attrs=st_round + [grey]) for g in G: disc.show_geodesic(g(z_vert), g(z_edge), attrs=st_round) # for [cl, zs] in ([green, faces], [blue, edges], [red, verts]): for [cl, zs] in ([red, verts], ): for z in zs: disc.show_point(z, fill_attrs=[white], stroke_attrs=[black]) # ------------------------------------------------------ I = Mobius() gens = [a, ~a, b, ~b, c, ~c] def get(word): g = reduce(mul, [gens[i] for i in word], I) return g for word in words: g = get(word) disc.show_point(g(z_tile), [blue.alpha(0.5)]) scale = 0.4 if labels: for (word, label) in labels.items(): g = reduce(mul, [gens[w] for w in reversed(word)], I) disc.show_label(g(z_tile), label, scale) else: for (g, label) in [ (I, r"$\star$"), (a, r"$a$"), (b, r"$b$"), (c, r"$c$"), #(c**2, r"$c^2$"), #(c**3, r"$c^3$"), ]: disc.show_label(g(z_tile), label, scale) for rel in rels: g = get(reversed(rel)) disc.show_label(g(z_tile), "I", scale) disc.fini() disc.save(name)
def main_bring(): # build the rotation group generators a, b = [g.todisc() for g in mktriangle(5, 2, 5)] disc = Disc() z_face = 0j z_vert = (a * b).inner_fixed() gamma = Geodesic.construct(z_vert, (~a)(z_vert)) z_edge = gamma.z2 # midpoint g_face = gamma.get_refl() gamma = Geodesic.construct(z_face, z_vert) g_edge = gamma.get_refl() g_vert = Mobius.conjugate() gens = [g_face, g_edge, g_vert] gens = gens + [~g for g in gens] G = mulclose(gens, verbose=True, maxsize=8000) # 8000 is enough faces, edges, verts = [], [], [] for g in G: #disc.show_geodesic(g(z_face), g(z_vert), attrs=[grey]) #disc.show_geodesic(g(z_face), g(z_edge), attrs=[grey]) faces.append(g(z_face)) edges.append(g(z_edge)) verts.append(g(z_vert)) for g in G: disc.show_geodesic(g(z_vert), g(z_edge), attrs=st_round) # break #disc.show_polygon([z_face, z_edge, z_vert], st_fill=[grey]) #disc.show_point(z_vert, radius=0.1) #disc.show_point((~a)(z_vert), radius=0.1) #disc.show_point(z_edge, radius=0.1) # z1, z2 = z_vert, a(z_vert) # faces.append(0.j) # for i in range(5): # disc.show_geodesic(z1, z2) # gamma = Geodesic.construct(z1, z2) # disc.show_geodesic(0, z1) # disc.show_geodesic(0, gamma.z2) # edges.append(gamma.z2) # verts.append(gamma.z0) # #g = gamma.get_refl() # #disc.show_point(g(0)) # z1, z2 = z2, a(z2) for z in edges: disc.show_qubit(z) #for [cl, zs] in ([green, faces], [blue, edges], [red, verts]): # for z in zs: # disc.show_point(z, [cl]) I = Mobius() z = 0.j pts0 = [] for (g, label) in [ (I, "1"), (b, "6"), (a * b, "2"), (a * a * b, "3"), (a * a * a * b, "4"), (a * a * a * a * b, "5"), (b * a * b, "8"), (a * b * a * b, "10"), (a * a * b * a * b, "7"), (a * a * a * b * a * b, "9"), (a * a * a * a * b * a * b, "11"), (b * a * b * a * b, "7"), (a * b * a * b * a * b, "9"), (a * a * b * a * b * a * b, "11"), (a * a * a * b * a * b * a * b, "8"), (a * a * a * a * b * a * b * a * b, "10"), (a * b * a * a * b, "5"), (a * a * b * a * a * b, "6"), (a * a * a * b * a * a * b, "2"), (a * a * a * a * b * a * a * b, "3"), (a * a * a * a * a * b * a * a * b, "4"), (b * a * a * a * b, "3"), (a * b * a * a * a * b, "4"), (a * a * b * a * a * a * b, "5"), (a * a * a * b * a * a * a * b, "6"), (a * a * a * a * b * a * a * a * b, "2"), (b * a * a * a * a * b * a * b * a * b, "7"), (a * b * a * a * a * a * b * a * b * a * b, "9"), (a * a * b * a * a * a * a * b * a * b * a * b, "11"), (a * a * a * b * a * a * a * a * b * a * b * a * b, "8"), (a * a * a * a * b * a * a * a * a * b * a * b * a * b, "10"), (b * a * a * a * a * b * a * b, "12"), (a * b * a * a * a * a * b * a * b, "12"), (a * a * b * a * a * a * a * b * a * b, "12"), (a * a * a * b * a * a * a * a * b * a * b, "12"), (a * a * a * a * b * a * a * a * a * b * a * b, "12"), (b * a * b * a * a * a * a * b, "12"), (a * b * a * b * a * a * a * a * b, "12"), (a * a * b * a * b * a * a * a * a * b, "12"), (a * a * a * b * a * b * a * a * a * a * b, "12"), (a * a * a * a * b * a * b * a * a * a * a * b, "12"), (b * a * a * b * a * b, "10"), (a * b * a * a * b * a * b, "7"), (a * a * b * a * a * b * a * b, "9"), (a * a * a * b * a * a * b * a * b, "11"), (a * a * a * a * b * a * a * b * a * b, "8"), ]: z1 = g(z) z1 = 0.98 * z1 disc.show_label(z1, label) #pts0.append(z1) #disc.show_point(z1, [red], radius=0.02) disc.fini() disc.save("brings-curve")
def get_refl(self): z0, z1, z2 = self.z0, self.z1, self.z2 g = Mobius.send(z0, z1, z2, -1, 0., 1.) C = Mobius(1, 0, 0, 1, True) # conjugate return (~g) * C * g