def _draw_funddom_d(coset_reps,format="MP",z0=I): r""" Draw a fundamental domain for self in the circle model INPUT: - ''format'' -- (default 'Disp') How to present the f.d. = 'S' -- Display directly on the screen - z0 -- (default I) the upper-half plane is mapped to the disk by z-->(z-z0)/(z-z0.conjugate()) EXAMPLES:: sage: G=MySubgroup(Gamma0(3)) sage: G._draw_funddom_d() """ # The fundamental domain consists of copies of the standard fundamental domain pi=RR.pi() from sage.plot.plot import (Graphics,line) g=Graphics() bdcirc=_circ_arc(0 ,2 *pi,0 ,1 ,1000 ) g=g+bdcirc # Corners x1=-RR(0.5) ; y1=RR(sqrt(3 )/2) x2=RR(0.5) ; y2=RR(sqrt(3 )/2) z_inf=1 l1 = _geodesic_between_two_points_d(x1,y1,x1,infinity) l2 = _geodesic_between_two_points_d(x2,y2,x2,infinity) c0 = _geodesic_between_two_points_d(x1,y1,x2,y2) tri=c0+l1+l2 g=g+tri for A in coset_reps: [a,b,c,d]=A if(a==1 and b==0 and c==0 and d==1 ): continue if(a<0 ): a=-a; b=-b; c=-c; d=-1 if(c==0 ): # then this is easier l1 = _geodesic_between_two_points_d(x1+b,y1,x1+b,infinity) l2 = _geodesic_between_two_points_d(x2+b,y2,x2+b,infinity) c0 = _geodesic_between_two_points_d(x1+b,y1,x2+b,y2) # c0=line(L0); l1=line(L1); l2=line(L2); l3=line(L3) tri=c0+l1+l2 g=g+tri else: den=(c*x1+d)**2 +c**2 *y1**2 x1_t=(a*c*(x1**2 +y1**2 )+(a*d+b*c)*x1+b*d)/den y1_t=y1/den den=(c*x2+d)**2 +c**2 *y2**2 x2_t=(a*c*(x2**2 +y2**2 )+(a*d+b*c)*x2+b*d)/den y2_t=y2/den inf_t=a/c c0=_geodesic_between_two_points_d(x1_t,y1_t,x2_t,y2_t) c1=_geodesic_between_two_points_d(x1_t,y1_t,inf_t,0.0 ) c2=_geodesic_between_two_points_d(x2_t,y2_t,inf_t,0.0 ) tri=c0+c1+c2 g=g+tri g.xmax(1 ) g.ymax(1 ) g.xmin(-1 ) g.ymin(-1 ) g.set_aspect_ratio(1 ) return g
def triangulation(self): r""" Plot a regular polygon with some diagonals. If ``self`` is positive and integral then this will be a triangulation. .. PLOT:: :width: 600 px G = path_tableaux.FriezePattern([1,2,7,5,3,7,4,1]).triangulation() p = graphics_array(G, 7, 6) sphinx_plot(p) EXAMPLES:: sage: path_tableaux.FriezePattern([1,2,7,5,3,7,4,1]).triangulation() Graphics object consisting of 25 graphics primitives sage: path_tableaux.FriezePattern([1,2,1/7,5,3]).triangulation() Graphics object consisting of 12 graphics primitives sage: K.<sqrt2> = NumberField(x^2-2) sage: path_tableaux.FriezePattern([1,sqrt2,1,sqrt2,3,2*sqrt2,5,3*sqrt2,1], field=K).triangulation() Graphics object consisting of 24 graphics primitives """ n = len(self) - 1 cd = CylindricalDiagram(self).diagram from sage.plot.plot import Graphics from sage.plot.line import line from sage.plot.text import text from sage.functions.trig import sin, cos from sage.all import pi G = Graphics() G.set_aspect_ratio(1.0) vt = [(cos(2 * theta * pi / (n)), sin(2 * theta * pi / (n))) for theta in range(n + 1)] for i, p in enumerate(vt): G += text(str(i), [1.05 * p[0], 1.05 * p[1]]) for i, r in enumerate(cd): for j, a in enumerate(r[:n]): if a == 1: G += line([vt[i], vt[j]]) G.axes(False) return G
def _draw_funddom_d(coset_reps, format="MP", z0=I): r""" Draw a fundamental domain for self in the circle model INPUT: - ''format'' -- (default 'Disp') How to present the f.d. = 'S' -- Display directly on the screen - z0 -- (default I) the upper-half plane is mapped to the disk by z-->(z-z0)/(z-z0.conjugate()) EXAMPLES:: sage: G=MySubgroup(Gamma0(3)) sage: G._draw_funddom_d() """ # The fundamental domain consists of copies of the standard fundamental domain pi = RR.pi() from sage.plot.plot import Graphics g = Graphics() bdcirc = _circ_arc(0, 2 * pi, 0, 1, 1000) g = g + bdcirc # Corners x1 = -RR(0.5) y1 = RR(sqrt(3) / 2) x2 = RR(0.5) y2 = RR(sqrt(3) / 2) l1 = _geodesic_between_two_points_d(x1, y1, x1, infinity) l2 = _geodesic_between_two_points_d(x2, y2, x2, infinity) c0 = _geodesic_between_two_points_d(x1, y1, x2, y2) tri = c0 + l1 + l2 g = g + tri for A in coset_reps: [a, b, c, d] = A if (a == 1 and b == 0 and c == 0 and d == 1): continue if (a < 0): a = -a b = -b c = -c d = -1 if (c == 0): # then this is easier l1 = _geodesic_between_two_points_d(x1 + b, y1, x1 + b, infinity) l2 = _geodesic_between_two_points_d(x2 + b, y2, x2 + b, infinity) c0 = _geodesic_between_two_points_d(x1 + b, y1, x2 + b, y2) # c0=line(L0); l1=line(L1); l2=line(L2); l3=line(L3) tri = c0 + l1 + l2 g = g + tri else: den = (c * x1 + d)**2 + c**2 * y1**2 x1_t = (a * c * (x1**2 + y1**2) + (a * d + b * c) * x1 + b * d) / den y1_t = y1 / den den = (c * x2 + d)**2 + c**2 * y2**2 x2_t = (a * c * (x2**2 + y2**2) + (a * d + b * c) * x2 + b * d) / den y2_t = y2 / den inf_t = a / c c0 = _geodesic_between_two_points_d(x1_t, y1_t, x2_t, y2_t) c1 = _geodesic_between_two_points_d(x1_t, y1_t, inf_t, 0.0) c2 = _geodesic_between_two_points_d(x2_t, y2_t, inf_t, 0.0) tri = c0 + c1 + c2 g = g + tri g.xmax(1) g.ymax(1) g.xmin(-1) g.ymin(-1) g.set_aspect_ratio(1) return g
def plot(self, color='rainbow', orientation='bottom-top', gap=0.05, aspect_ratio=1, axes=False, **kwds): """ Plot the braid The following options are available: - ``color`` -- (default: ``'rainbow'``) the color of the strands. Possible values are: * ``'rainbow'``, uses :meth:`~sage.plot.colors.rainbow` according to the number of strands. * a valid color name for :meth:`~sage.plot.bezier_path` and :meth:`~sage.plot.line`. Used for all strands. * a list or a tuple of colors for each individual strand. - ``orientation`` -- (default: ``'bottom-top'``) determines how the braid is printed. The possible values are: * ``'bottom-top'``, the braid is printed from bottom to top * ``'top-bottom'``, the braid is printed from top to bottom * ``'left-right'``, the braid is printed from left to right - ``gap`` -- floating point number (default: 0.05). determines the size of the gap left when a strand goes under another. - ``aspect_ratio`` -- floating point number (default: ``1``). The aspect ratio. - ``**kwds`` -- other keyword options that are passed to :meth:`~sage.plot.bezier_path` and :meth:`~sage.plot.line`. EXAMPLES:: sage: B = BraidGroup(4, 's') sage: b = B([1, 2, 3, 1, 2, 1]) sage: b.plot() sage: b.plot(color=["red", "blue", "red", "blue"]) sage: B.<s,t> = BraidGroup(3) sage: b = t^-1*s^2 sage: b.plot(orientation="left-right", color="red") """ from sage.plot.bezier_path import bezier_path from sage.plot.plot import Graphics, line from sage.plot.colors import rainbow if orientation=='top-bottom': orx = 0 ory = -1 nx = 1 ny = 0 elif orientation=='left-right': orx = 1 ory = 0 nx = 0 ny = -1 elif orientation=='bottom-top': orx = 0 ory = 1 nx = 1 ny = 0 else: raise ValueError('unknown value for "orientation"') n = self.strands() if isinstance(color, (list, tuple)): if len(color) != n: raise TypeError("color (=%s) must contain exactly %d colors" % (color, n)) col = list(color) elif color == "rainbow": col = rainbow(n) else: col = [color]*n braid = self.Tietze() a = Graphics() op = gap for i, m in enumerate(braid): for j in range(n): if m==j+1: a += bezier_path([[(j*nx+i*orx, i*ory+j*ny), (j*nx+orx*(i+0.25), j*ny+ory*(i+0.25)), (nx*(j+0.5)+orx*(i+0.5), ny*(j+0.5)+ory*(i+0.5))], [(nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)), (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col[j], **kwds) elif m==j: a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)), (nx*(j-0.5+4*op)+orx*(i+0.5-2*op), ny*(j-0.5+4*op)+ory*(i+0.5-2*op)), (nx*(j-0.5+2*op)+orx*(i+0.5-op), ny*(j-0.5+2*op)+ory*(i+0.5-op))]], color=col[j], **kwds) a += bezier_path([[(nx*(j-0.5-2*op)+orx*(i+0.5+op), ny*(j-0.5-2*op)+ory*(i+0.5+op)), (nx*(j-0.5-4*op)+orx*(i+0.5+2*op), ny*(j-0.5-4*op)+ory*(i+0.5+2*op)), (nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)), (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col[j], **kwds) col[j], col[j-1] = col[j-1], col[j] elif -m==j+1: a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)), (nx*(j+0.5-4*op)+orx*(i+0.5-2*op), ny*(j+0.5-4*op)+ory*(i+0.5-2*op)), (nx*(j+0.5-2*op)+orx*(i+0.5-op), ny*(j+0.5-2*op)+ory*(i+0.5-op))]], color=col[j], **kwds) a += bezier_path([[(nx*(j+0.5+2*op)+orx*(i+0.5+op), ny*(j+0.5+2*op)+ory*(i+0.5+op)), (nx*(j+0.5+4*op)+orx*(i+0.5+2*op), ny*(j+0.5+4*op)+ory*(i+0.5+2*op)), (nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)), (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col[j], **kwds) elif -m==j: a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)), (nx*(j-0.5)+orx*(i+0.5), ny*(j-0.5)+ory*(i+0.5))], [(nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)), (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col[j], **kwds) col[j], col[j-1] = col[j-1], col[j] else: a += line([(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+1), ny*j+ory*(i+1))], color=col[j], **kwds) a.set_aspect_ratio(aspect_ratio) a.axes(axes) return a
def plot(self, color='blue', orientation='bottom-top', gap=0.05, aspect_ratio=1, axes=False, **kwds): """ Plot the braid The following options are available: - ``orientation`` - (default: ``'bottom-top'``) determines how the braid is printed. The possible values are: * ``'bottom-top'``, the braid is printed from bottom to top * ``'top-bottom'``, the braid is printed from top to bottom * ``'left-right'``, the braid is printed from left to right - ``gap`` -- floating point number (default: 0.05). determines the size of the gap left when a strand goes under another. - ``aspect_ratio`` -- floating point number (default: ``1``). The aspect ratio. - ``**kwds`` -- other keyword options that are passed to :meth:`~sage.plot.bezier_path` and :meth:`~sage.plot.line`. EXAMPLES:: sage: B = BraidGroup(4, 's') sage: b = B([1, 2, 3, 1, 2, 1]) sage: b.plot() """ from sage.plot.bezier_path import bezier_path from sage.plot.plot import Graphics, line if orientation=='top-bottom': orx = 0 ory = -1 nx = 1 ny = 0 elif orientation=='left-right': orx = 1 ory = 0 nx = 0 ny = -1 elif orientation=='bottom-top': orx = 0 ory = 1 nx = 1 ny = 0 else: raise ValueError('unknown value for "orientation"') col = color br = self.Tietze() n = self.strands() a = Graphics() op = gap for i in range(len(br)): m = br[i] for j in range(n): if m==j+1: a += bezier_path([[(j*nx+i*orx, i*ory+j*ny), (j*nx+orx*(i+0.25), j*ny+ory*(i+0.25)), (nx*(j+0.5)+orx*(i+0.5), ny*(j+0.5)+ory*(i+0.5))], [(nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)), (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col, **kwds) elif m==j: a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)), (nx*(j-0.5+4*op)+orx*(i+0.5-2*op), ny*(j-0.5+4*op)+ory*(i+0.5-2*op)), (nx*(j-0.5+2*op)+orx*(i+0.5-op), ny*(j-0.5+2*op)+ory*(i+0.5-op))]], color=col, **kwds) a += bezier_path([[(nx*(j-0.5-2*op)+orx*(i+0.5+op), ny*(j-0.5-2*op)+ory*(i+0.5+op)), (nx*(j-0.5-4*op)+orx*(i+0.5+2*op), ny*(j-0.5-4*op)+ory*(i+0.5+2*op)), (nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)), (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col, **kwds) elif -m==j+1: a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)), (nx*(j+0.5-4*op)+orx*(i+0.5-2*op), ny*(j+0.5-4*op)+ory*(i+0.5-2*op)), (nx*(j+0.5-2*op)+orx*(i+0.5-op), ny*(j+0.5-2*op)+ory*(i+0.5-op))]], color=col, **kwds) a += bezier_path([[(nx*(j+0.5+2*op)+orx*(i+0.5+op), ny*(j+0.5+2*op)+ory*(i+0.5+op)), (nx*(j+0.5+4*op)+orx*(i+0.5+2*op), ny*(j+0.5+4*op)+ory*(i+0.5+2*op)), (nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)), (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col, **kwds) elif -m==j: a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)), (nx*(j-0.5)+orx*(i+0.5), ny*(j-0.5)+ory*(i+0.5))], [(nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)), (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col, **kwds) else: a += line([(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+1), ny*j+ory*(i+1))], color=col, **kwds) a.set_aspect_ratio(aspect_ratio) a.axes(axes) return a
def plot(self, color='blue', orientation='bottom-top', gap=0.05, aspect_ratio=1, axes=False, **kwds): """ Plot the braid The following options are available: - ``orientation`` - (default: ``'bottom-top'``) determines how the braid is printed. The possible values are: * ``'bottom-top'``, the braid is printed from bottom to top * ``'top-bottom'``, the braid is printed from top to bottom * ``'left-right'``, the braid is printed from left to right - ``gap`` -- floating point number (default: 0.05). determines the size of the gap left when a strand goes under another. - ``aspect_ratio`` -- floating point number (default: ``1``). The aspect ratio. - ``**kwds`` -- other keyword options that are passed to :meth:`~sage.plot.bezier_path` and :meth:`~sage.plot.line`. EXAMPLES:: sage: B = BraidGroup(4, 's') sage: b = B([1, 2, 3, 1, 2, 1]) sage: b.plot() """ from sage.plot.bezier_path import bezier_path from sage.plot.plot import Graphics, line if orientation=='top-bottom': orx = 0 ory = -1 nx = 1 ny = 0 elif orientation=='left-right': orx = 1 ory = 0 nx = 0 ny = -1 elif orientation=='bottom-top': orx = 0 ory = 1 nx = 1 ny = 0 else: raise ValueError('unknown value for "orientation"') col = color br = self.Tietze() n = self.strands() a = Graphics() op = gap for i in range(len(br)): m = br[i] for j in range(n): if m==j+1: a += bezier_path([[(j*nx+i*orx, i*ory+j*ny), (j*nx+orx*(i+0.25), j*ny+ory*(i+0.25)), (nx*(j+0.5)+orx*(i+0.5), ny*(j+0.5)+ory*(i+0.5))], [(nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)), (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col, **kwds) elif m==j: a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)), (nx*(j-0.5+4*op)+orx*(i+0.5-2*op), ny*(j-0.5+4*op)+ory*(i+0.5-2*op)), (nx*(j-0.5+2*op)+orx*(i+0.5-op), ny*(j-0.5+2*op)+ory*(i+0.5-op))]], color=col, **kwds) a += bezier_path([[(nx*(j-0.5-2*op)+orx*(i+0.5+op), ny*(j-0.5-2*op)+ory*(i+0.5+op)), (nx*(j-0.5-4*op)+orx*(i+0.5+2*op), ny*(j-0.5-4*op)+ory*(i+0.5+2*op)), (nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)), (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col, **kwds) elif -m==j+1: a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)), (nx*(j+0.5-4*op)+orx*(i+0.5-2*op), ny*(j+0.5-4*op)+ory*(i+0.5-2*op)), (nx*(j+0.5-2*op)+orx*(i+0.5-op), ny*(j+0.5-2*op)+ory*(i+0.5-op))]], color=col, **kwds) a += bezier_path([[(nx*(j+0.5+2*op)+orx*(i+0.5+op), ny*(j+0.5+2*op)+ory*(i+0.5+op)), (nx*(j+0.5+4*op)+orx*(i+0.5+2*op), ny*(j+0.5+4*op)+ory*(i+0.5+2*op)), (nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)), (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col, **kwds) elif -m==j: a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)), (nx*(j-0.5)+orx*(i+0.5), ny*(j-0.5)+ory*(i+0.5))], [(nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)), (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col, **kwds) else: a += line([(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+1), ny*j+ory*(i+1))], color=col, **kwds) a.set_aspect_ratio(aspect_ratio) a.axes(axes) return a
def plot(self, size=[[0],[0]], projection='usual', simple_roots=True, fundamental_weights=True, alcovewalks=[]): r""" Return a graphics object built from a space of weight(space/lattice). There is a different technic to plot if the Cartan type is affine or not. The graphics returned is a Graphics object. This function is experimental, and is subject to short term evolutions. EXAMPLES:: By default, the plot returned has no axes and the ratio between axes is 1. sage: G = RootSystem(['C',2]).weight_lattice().plot() sage: G.axes(True) sage: G.set_aspect_ratio(2) For a non affine Cartan type, the plot method work for type with 2 generators, it will draw the hyperlane(line for this dimension) accrow the fundamentals weights. sage: G = RootSystem(['A',2]).weight_lattice().plot() sage: G = RootSystem(['B',2]).weight_lattice().plot() sage: G = RootSystem(['G',2]).weight_lattice().plot() The plot returned has a size of one fundamental polygon by default. We can ask plot to give a bigger plot by using the argument size sage: G = RootSystem(['G',2,1]).weight_space().plot(size = [[0..1],[-1..1]]) sage: G = RootSystem(['A',2,1]).weight_space().plot(size = [[-1..1],[-1..1]]) A very important argument is the projection which will draw the plot. There are some usual projections is this method. If you want to draw in the plane a very special Cartan type, Sage will ask you to specify the projection. The projection is a matrix over a ring. In practice, calcul over float is a good way to draw. sage: L = RootSystem(['A',2,1]).weight_space() sage: G = L.plot(projection=matrix(RR, [[0,0.5,-0.5],[0,0.866,0.866]])) sage: G = RootSystem(['C',2,1]).weight_space().plot() By default, the plot method draw the simple roots, this can be disabled by setting the argument simple_roots=False sage: G = RootSystem(['A',2]).weight_space().plot(simple_roots=False) By default, the plot method draw the fundamental weights,this can be disabled by setting the argument fundamental_weights=False sage: G = RootSystem(['A',2]).weight_space().plot(fundamental_weights=False, simple_roots=False) There is in a plot an argument to draw alcoves walks. The good way to do this is to use the crystals theory. the plot method contains only the drawing part... sage: L = RootSystem(['A',2,1]).weight_space() sage: G = L.plot(size=[[-1..1],[-1..1]],alcovewalks=[[0,2,0,1,2,1,2,0,2,1]]) """ from sage.plot.plot import Graphics from sage.plot.line import line from cartan_type import CartanType from sage.matrix.constructor import matrix from sage.rings.all import QQ, RR from sage.plot.arrow import arrow from sage.plot.point import point # We begin with an empty plot G G = Graphics() ct = self.cartan_type() n = ct.n # Define a set of colors # TODO : Colors in option ? colors=[(0,1,0),(1,0,0),(0,0,1),(1,1,0),(0,1,1),(1,0,1)] # plot the affine types: if ct.is_affine(): # Check the projection # TODO : try to have usual_projection for main plotable types if projection == 'usual': if ct == CartanType(['A',2,1]): projection = matrix(RR, [[0,0.5,-0.5],[0,0.866,0.866]]) elif ct == CartanType(['C',2,1]): projection = matrix(QQ, [[0,1,1],[0,0,1]]) elif ct == CartanType(['G',2,1]): projection = matrix(RR, [[0,0.5,0],[0,0.866,1.732]]) else: raise 'There is no usual projection for this Cartan type, you have to give one in argument' assert(n + 1 == projection.ncols()) assert(2 == projection.nrows()) # Check the size is correct with the lattice assert(len(size) == n) # Select the center of the translated fundamental polygon to plot translation_factors = ct.translation_factors() simple_roots = self.simple_roots() translation_vectors = [translation_factors[i]*simple_roots[i] for i in ct.classical().index_set()] initial = [[]] for i in range(n): prod_list = [] for elem in size[i]: for partial_list in initial: prod_list.append( [elem]+partial_list ); initial = prod_list; part_lattice = [] for combinaison in prod_list: elem_lattice = self.zero() for i in range(n): elem_lattice = elem_lattice + combinaison[i]*translation_vectors[i] part_lattice.append(elem_lattice) # Get the vertices of the fundamental alcove fundamental_weights = self.fundamental_weights() vertices = map(lambda x: (1/x.level())*x, fundamental_weights.list()) # Recup the group which act on the fundamental polygon classical = self.weyl_group().classical() for center in part_lattice: for w in classical: # for each center of polygon and each element of classical # parabolic subgroup, we have to draw an alcove. #first, iterate over pairs of fundamental weights, drawing lines border of polygons: for i in range(1,n+1): for j in range(i+1,n+1): p1=projection*((w.action(vertices[i])).to_vector() + center.to_vector()) p2=projection*((w.action(vertices[j])).to_vector() + center.to_vector()) G+=line([p1,p2],rgbcolor=(0,0,0),thickness=2) #next, get all lines from point to a fundamental weight, that separe different #chanber in a same polygon (important: associate a color with a fundamental weight) pcenter = projection*(center.to_vector()) for i in range(1,n+1): p3=projection*((w.action(vertices[i])).to_vector() + center.to_vector()) G+=line([p3,pcenter], rgbcolor=colors[n-i+1]) #Draw alcovewalks #FIXME : The good way to draw this is to use the alcoves walks works made in Cristals #The code here just draw like example and import the good things. rho = (1/self.rho().level())*self.rho() W = self.weyl_group() for walk in alcovewalks: target = W.from_reduced_word(walk).action(rho) for i in range(len(walk)): walk.pop() origin = W.from_reduced_word(walk).action(rho) G+=arrow(projection*(origin.to_vector()),projection*(target.to_vector()), rgbcolor=(0.6,0,0.6), width=1, arrowsize=5) target = origin else: # non affine plot # Check the projection # TODO : try to have usual_projection for main plotable types if projection == 'usual': if ct == CartanType(['A',2]): projection = matrix(RR, [[0.5,-0.5],[0.866,0.866]]) elif ct == CartanType(['B',2]): projection = matrix(QQ, [[1,0],[1,1]]) elif ct == CartanType(['C',2]): projection = matrix(QQ, [[1,1],[0,1]]) elif ct == CartanType(['G',2]): projection = matrix(RR, [[0.5,0],[0.866,1.732]]) else: raise 'There is no usual projection for this Cartan type, you have to give one in argument' # Get the fundamental weights fundamental_weights = self.fundamental_weights() WeylGroup = self.weyl_group() #Draw not the alcove but the cones delimited by the hyperplanes #The size of the line depend of the fundamental weights. pcenter = projection*(self.zero().to_vector()) for w in WeylGroup: for i in range(1,n+1): p3=3*projection*((w.action(fundamental_weights[i])).to_vector()) G+=line([p3,pcenter], rgbcolor=colors[n-i+1]) #Draw the simple roots if simple_roots: SimpleRoots = self.simple_roots() if ct.is_affine(): G+=arrow((0,0), projection*(SimpleRoots[0].to_vector()), rgbcolor=(0,0,0)) for j in range(1,n+1): G+=arrow((0,0),projection*(SimpleRoots[j].to_vector()), rgbcolor=colors[j]) #Draw the fundamental weights if fundamental_weights: FundWeight = self.fundamental_weights() for j in range(1,n+1): G+=point(projection*(FundWeight[j].to_vector()), rgbcolor=colors[j], pointsize=60) G.set_aspect_ratio(1) G.axes(False) return G