def main6(): c = continued_fraction([Integer(1)] * (8)) v = [(i, c.p(i) / c.q(i)) for i in range(c.length())] P = point(v, rgbcolor=(0, 0, 1), pointsize=40) L = line(v, rgbcolor=(0.5, 0.5, 0.5)) L2 = line([(Integer(0), c.value()), (c.length() - Integer(1), c.value())], thickness=0.5, rgbcolor=(0.7, 0, 0)) (L + L2 + P).save(filename="continued_fraction.png") print("Graph is saved as continued_fraction.png")
def draw_transformed_triangle_H(A, xmax=20): r""" Draw the modular triangle translated by A=[a,b,c,d] """ #print "A=",A,type(A) pi = RR.pi() pi_3 = pi / RR(3.0) from sage.plot.plot import (Graphics, line) from sage.functions.trig import (cos, sin) x1 = RR(-0.5) y1 = RR(sqrt(3) / 2) x2 = RR(0.5) y2 = RR(sqrt(3) / 2) a, b, c, d = A #[0,0]; b=A[0,1]; c=A[1,0]; d=A[1,1] if a < 0: a = RR(-a) b = RR(-b) c = RR(-c) d = RR(-d) else: a = RR(a) b = RR(b) c = RR(c) d = RR(d) if c == 0: # then this is easier if a * d <> 0: a = a / d b = b / d L0 = [[ a * cos(pi_3 * RR(i / 100.0)) + b, a * sin(pi_3 * RR(i / 100.0)) ] for i in range(100, 201)] L1 = [[a * x1 + b, a * y1], [a * x1 + b, xmax]] L2 = [[a * x2 + b, a * y2], [a * x2 + b, xmax]] L3 = [[a * x2 + b, xmax], [a * x1 + b, xmax]] c0 = line(L0) l1 = line(L1) l2 = line(L2) l3 = line(L3) tri = c0 + l1 + l3 + l2 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 #print "A=",A #print "arg1=",x1_t,y1_t,x2_t,y2_t c0 = _geodesic_between_two_points(x1_t, y1_t, x2_t, y2_t) #print "arg1=",x1_t,y1_t,inf_t c1 = _geodesic_between_two_points(x1_t, y1_t, inf_t, 0.) #print "arg1=",x2_t,y2_t,inf_t c2 = _geodesic_between_two_points(x2_t, y2_t, inf_t, 0.0) tri = c0 + c1 + c2 return tri
def getLfunctionPlot(request, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9): pythonL = generateLfunctionFromUrl( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, to_dict(request.args)) if not pythonL: return "" plotrange = 30 if hasattr(pythonL, 'plotpoints'): F = p2sage(pythonL.plotpoints) plotrange = min(plotrange, F[-1][0]) # F[-1][0] is the highest t-coordinated that we have a value for L else: # obsolete, because lfunc_data comes from DB? L = pythonL.sageLfunction if not hasattr(L, "hardy_z_function"): return None plotStep = .1 if pythonL._Ltype not in ["riemann", "maass", "ellipticmodularform", "ellipticcurve"]: plotrange = 12 F = [(i, L.hardy_z_function(i).real()) for i in srange(-1*plotrange, plotrange, plotStep)] interpolation = spline(F) F_interp = [(i, interpolation(i)) for i in srange(-1*plotrange, plotrange, 0.05)] p = line(F_interp) # p = line(F) # temporary hack while the correct interpolation is being implemented styleLfunctionPlot(p, 10) fn = tempfile.mktemp(suffix=".png") p.save(filename=fn) data = file(fn).read() os.remove(fn) return data
def graphical(ao): r""" Return a sage graphics representation of the given acyclic orientation. """ from sage.all import Graphics, point, line assert is_orientation(ao) n, ascents, descents = ao # compute heights height = [0]*n for _ in range(n): for (i, j) in ascents: height[j] = max(height[j], height[i]+1) for (i, j) in descents: height[i] = max(height[i], height[j]+1) # compute the extent of each interval left = range(n) right = range(n) for (i, j) in ascents: right[i] += .75 left[j] -= .75 for (i, j) in descents: right[i] += .75 left[j] -= .75 result = Graphics() # put in the ascents and descents for (i, j) in ascents: result += line([(i, height[i]), (j, height[j])], color='red', thickness=2) for (i, j) in descents: result += line([(i, height[i]), (j, height[j])], color='blue', thickness=2) # then put in the intervals for i in range(n): result += line([(left[i], height[i]), (right[i], height[i])], color='black', thickness=2) result += point([(i, height[i])], color='black', size=100) # reset some annoying options result.axes(False) result.set_aspect_ratio(1) return result
def _geodesic_between_two_points(x1, y1, x2, y2): r""" Geodesic path between two points hyperbolic upper half-plane INPUTS: - ''(x1,y1)'' -- starting point (0<y1<=infinity) - ''(x2,y2)'' -- ending point (0<y2<=infinity) - ''z0'' -- (default I) the point in the upper corresponding to the point 0 in the disc. I.e. the transform is w -> (z-I)/(z+I) OUTPUT: - ''ca'' -- a polygonal approximation of a circular arc centered at c and radius r, starting at t0 and ending at t1 EXAMPLES:: sage: l=_geodesic_between_two_points(0.1,0.2,0.0,0.5) """ pi = RR.pi() from sage.plot.plot import line from sage.functions.trig import arcsin # logging.debug("z1=%s,%s" % (x1,y1)) # logging.debug("z2=%s,%s" % (x2,y2)) if abs(x1 - x2) < 1e-10: # The line segment [x=x1, y0<= y <= y1] return line([[x1, y1], [x2, y2]]) # [0,0,x0,infinity] c = RR(y1 ** 2 - y2 ** 2 + x1 ** 2 - x2 ** 2) / RR(2 * (x1 - x2)) r = RR(sqrt(y1 ** 2 + (x1 - c) ** 2)) r1 = RR(y1 / r) r2 = RR(y2 / r) if abs(r1 - 1) < 1e-12: r1 = RR(1.0) elif abs(r2 + 1) < 1e-12: r2 = -RR(1.0) if abs(r2 - 1) < 1e-12: r2 = RR(1.0) elif abs(r2 + 1) < 1e-12: r2 = -RR(1.0) if x1 >= c: t1 = RR(arcsin(r1)) else: t1 = RR(pi) - RR(arcsin(r1)) if x2 >= c: t2 = RR(arcsin(r2)) else: t2 = RR(pi) - arcsin(r2) # tmid = (t1 + t2) * RR(0.5) # a0 = min(t1, t2) # a1 = max(t1, t2) # logging.debug("c,r=%s,%s" % (c,r)) # logging.debug("t1,t2=%s,%s"%(t1,t2)) return _circ_arc(t1, t2, c, r)
def _draw_funddom(coset_reps,format="S"): r""" Draw a fundamental domain for G. INPUT: - ``format`` -- (default 'Disp') How to present the f.d. - ``S`` -- Display directly on the screen EXAMPLES:: sage: G=MySubgroup(Gamma0(3)) sage: G._draw_funddom() """ pi=RR.pi() pi_3 = pi / RR(3.0) from sage.plot.plot import (Graphics,line) from sage.functions.trig import (cos,sin) g=Graphics() x1=RR(-0.5) ; y1=RR(sqrt(3 )/2 ) x2=RR(0.5) ; y2=RR(sqrt(3 )/2 ) xmax=RR(20.0) l1 = line([[x1,y1],[x1,xmax]]) l2 = line([[x2,y2],[x2,xmax]]) l3 = line([[x2,xmax],[x1,xmax]]) # This is added to make a closed contour c0=_circ_arc(RR(pi/3.0) ,RR(2.0*pi)/RR(3.0) ,0 ,1 ,100 ) tri=c0+l1+l3+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=RR(-a); b=RR(-b); c=RR(-c); d=RR(-d) else: a=RR(a); b=RR(b); c=RR(c); d=RR(d) if(c==0 ): # then this is easier L0 = [[cos(pi_3*RR(i/100.0))+b,sin(pi_3*RR(i/100.0))] for i in range(100 ,201 )] L1 = [[x1+b,y1],[x1+b,xmax]] L2 = [[x2+b,y2],[x2+b,xmax]] L3 = [[x2+b,xmax],[x1+b,xmax]] c0=line(L0); l1=line(L1); l2=line(L2); l3=line(L3) tri=c0+l1+l3+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(x1_t,y1_t,x2_t,y2_t) c1=_geodesic_between_two_points(x1_t,y1_t,inf_t,0. ) c2=_geodesic_between_two_points(x2_t,y2_t,inf_t,0.0) tri=c0+c1+c2 g=g+tri return g
def _geodesic_between_two_points(x1, y1, x2, y2): r""" Geodesic path between two points hyperbolic upper half-plane INPUTS: - ''(x1,y1)'' -- starting point (0<y1<=infinity) - ''(x2,y2)'' -- ending point (0<y2<=infinity) - ''z0'' -- (default I) the point in the upper corresponding to the point 0 in the disc. I.e. the transform is w -> (z-I)/(z+I) OUTPUT: - ''ca'' -- a polygonal approximation of a circular arc centered at c and radius r, starting at t0 and ending at t1 EXAMPLES:: sage: l=_geodesic_between_two_points(0.1,0.2,0.0,0.5) """ pi = RR.pi() from sage.plot.plot import line from sage.functions.trig import arcsin #print "z1=",x1,y1 #print "z2=",x2,y2 if (abs(x1 - x2) < 1E-10): # The line segment [x=x1, y0<= y <= y1] return line([[x1, y1], [x2, y2]]) #[0,0,x0,infinity] c = RR(y1**2 - y2**2 + x1**2 - x2**2) / RR(2 * (x1 - x2)) r = RR(sqrt(y1**2 + (x1 - c)**2)) r1 = RR(y1 / r) r2 = RR(y2 / r) if (abs(r1 - 1) < 1E-12): r1 = RR(1.0) elif (abs(r2 + 1) < 1E-12): r2 = -RR(1.0) if (abs(r2 - 1) < 1E-12): r2 = RR(1.0) elif (abs(r2 + 1) < 1E-12): r2 = -RR(1.0) if (x1 >= c): t1 = RR(arcsin(r1)) else: t1 = RR(pi) - RR(arcsin(r1)) if (x2 >= c): t2 = RR(arcsin(r2)) else: t2 = RR(pi) - arcsin(r2) tmid = (t1 + t2) * RR(0.5) a0 = min(t1, t2) a1 = max(t1, t2) #print "c,r=",c,r #print "t1,t2=",t1,t2 return _circ_arc(t1, t2, c, r)
def plot_norms(norms, block_size, bound): from sage.all import line from itertools import cycle n = len(norms[0]) colours = cycle([ "#4D4D4D", "#5DA5DA", "#FAA43A", "#60BD68", "#F17CB0", "#B2912F", "#B276B2", "#DECF3F", "#F15854" ]) base = colours.next() g = line(zip(range(n), norms[0]), legend_label="GSA", color=base, frame=True, axes=False, transparent=True, axes_labels=["$i$", "$2\\,\\log_2 \\|\mathbf{b}^*_i\\|$"]) g += line([(n - block_size, 0), (n - block_size, 0.99 * norms[0][n - block_size - 1])], color=base, linestyle='--') g += line(zip(range(n), norms[1]), legend_label="$\\|\\mathbf{e}^*_{i}\\|$", color=colours.next()) g += line(zip(range(n), norms[2]), legend_label="LLL", color=colours.next()) for i, _norms in enumerate(norms[3:]): if _norms[0] <= bound: thickness = 1.5 else: thickness = 1 g += line(zip(range(n), _norms), legend_label="tour %d" % i, color=colours.next(), thickness=thickness) if _norms[0] <= bound: break return g
def draw_transformed_triangle_H(A,xmax=20): r""" Draw the modular triangle translated by A=[a,b,c,d] """ #print "A=",A,type(A) pi=RR.pi() pi_3 = pi / RR(3.0) from sage.plot.plot import (Graphics,line) from sage.functions.trig import (cos,sin) x1=RR(-0.5) ; y1=RR(sqrt(3 )/2 ) x2=RR(0.5) ; y2=RR(sqrt(3 )/2 ) a,b,c,d = A #[0,0]; b=A[0,1]; c=A[1,0]; d=A[1,1] if a<0: a=RR(-a); b=RR(-b); c=RR(-c); d=RR(-d) else: a=RR(a); b=RR(b); c=RR(c); d=RR(d) if c==0: # then this is easier if a*d<>0: a=a/d; b=b/d; L0 = [[a*cos(pi_3*RR(i/100.0))+b,a*sin(pi_3*RR(i/100.0))] for i in range(100 ,201 )] L1 = [[a*x1+b,a*y1],[a*x1+b,xmax]] L2 = [[a*x2+b,a*y2],[a*x2+b,xmax]] L3 = [[a*x2+b,xmax],[a*x1+b,xmax]] c0=line(L0); l1=line(L1); l2=line(L2); l3=line(L3) tri=c0+l1+l3+l2 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 #print "A=",A #print "arg1=",x1_t,y1_t,x2_t,y2_t c0=_geodesic_between_two_points(x1_t,y1_t,x2_t,y2_t) #print "arg1=",x1_t,y1_t,inf_t c1=_geodesic_between_two_points(x1_t,y1_t,inf_t,0. ) #print "arg1=",x2_t,y2_t,inf_t c2=_geodesic_between_two_points(x2_t,y2_t,inf_t,0.0) tri=c0+c1+c2 return tri
def draw_funddom(coset_reps, format="S"): r""" Draw a fundamental domain for G. INPUT: - ``format`` -- (default 'Disp') How to present the f.d. - ``S`` -- Display directly on the screen EXAMPLES:: sage: G=MySubgroup(Gamma0(3)) sage: G._draw_funddom() """ pi = RR.pi() pi_3 = pi / RR(3.0) from sage.plot.plot import (Graphics, line) from sage.functions.trig import (cos, sin) g = Graphics() x1 = RR(-0.5) y1 = RR(sqrt(3) / 2) x2 = RR(0.5) y2 = RR(sqrt(3) / 2) xmax = RR(20.0) l1 = line([[x1, y1], [x1, xmax]]) l2 = line([[x2, y2], [x2, xmax]]) l3 = line([[x2, xmax], [x1, xmax]]) # This is added to make a closed contour c0 = _circ_arc(RR(pi / 3.0), RR(2.0 * pi) / RR(3.0), 0, 1, 100) tri = c0 + l1 + l3 + l2 g = g + tri for A in coset_reps: if list(A) == [1, 0, 0, 1]: continue tri = draw_transformed_triangle_H(A, xmax=xmax) g = g + tri return g
def draw_funddom(coset_reps,format="S"): r""" Draw a fundamental domain for G. INPUT: - ``format`` -- (default 'Disp') How to present the f.d. - ``S`` -- Display directly on the screen EXAMPLES:: sage: G=MySubgroup(Gamma0(3)) sage: G._draw_funddom() """ pi=RR.pi() pi_3 = pi / RR(3.0) from sage.plot.plot import (Graphics,line) from sage.functions.trig import (cos,sin) g=Graphics() x1=RR(-0.5) ; y1=RR(sqrt(3 )/2 ) x2=RR(0.5) ; y2=RR(sqrt(3 )/2 ) xmax=RR(20.0) l1 = line([[x1,y1],[x1,xmax]]) l2 = line([[x2,y2],[x2,xmax]]) l3 = line([[x2,xmax],[x1,xmax]]) # This is added to make a closed contour c0=_circ_arc(RR(pi/3.0) ,RR(2.0*pi)/RR(3.0) ,0 ,1 ,100 ) tri=c0+l1+l3+l2 g=g+tri for A in coset_reps: if list(A)==[1,0,0,1]: continue tri=draw_transformed_triangle_H(A,xmax=xmax) g=g+tri return g
def _circ_arc(t0, t1, c, r, num_pts=5000): r""" Circular arc INPUTS: - ''t0'' -- starting parameter - ''t1'' -- ending parameter - ''c'' -- center point of the circle - ''r'' -- radius of circle - ''num_pts'' -- (default 100) number of points on polygon OUTPUT: - ''ca'' -- a polygonal approximation of a circular arc centered at c and radius r, starting at t0 and ending at t1 EXAMPLES:: sage: ca=_circ_arc(0.1,0.2,0.0,1.0,100) """ from sage.plot.plot import line from sage.functions.trig import (cos, sin) t00 = t0 t11 = t1 ## To make sure the line is correct we reduce all arguments to the same branch, ## e.g. [0,2pi] pi = RR.pi() while (t00 < 0.0): t00 = t00 + RR(2.0 * pi) while (t11 < 0): t11 = t11 + RR(2.0 * pi) while (t00 > 2 * pi): t00 = t00 - RR(2.0 * pi) while (t11 > 2 * pi): t11 = t11 - RR(2.0 * pi) xc = CC(c).real() yc = CC(c).imag() L0 = [[ RR(r * cos(t00 + i * (t11 - t00) / num_pts)) + xc, RR(r * sin(t00 + i * (t11 - t00) / num_pts)) + yc ] for i in range(0, num_pts)] ca = line(L0) return ca
def show(self, unit=10, labels=True): from sage.all import circle, text, line, Graphics pos = self.basic_grid_embedding() for v, (a, b) in pos.items(): pos[v] = (unit * a, unit * b) if not labels: verts = [circle(p, 1, fill=True) for p in pos.values()] else: verts = [ text(repr(v), p, fontsize=20, color='black') for v, p in pos.items() ] verts += [circle(p, 1.5, fill=False) for p in pos.values()] edges = [ line([pos[e.tail], pos[e.head]]) for e in self.edges if e not in self.dummy ] G = sum(verts + edges, Graphics()) G.axes(False) return G
def _circ_arc(t0,t1,c,r,num_pts=5000 ): r""" Circular arc INPUTS: - ''t0'' -- starting parameter - ''t1'' -- ending parameter - ''c'' -- center point of the circle - ''r'' -- radius of circle - ''num_pts'' -- (default 100) number of points on polygon OUTPUT: - ''ca'' -- a polygonal approximation of a circular arc centered at c and radius r, starting at t0 and ending at t1 EXAMPLES:: sage: ca=_circ_arc(0.1,0.2,0.0,1.0,100) """ from sage.plot.plot import line from sage.functions.trig import (cos,sin) t00=t0; t11=t1 ## To make sure the line is correct we reduce all arguments to the same branch, ## e.g. [0,2pi] pi=RR.pi() while(t00<0.0): t00=t00+RR(2.0*pi) while(t11<0): t11=t11+RR(2.0*pi) while(t00>2*pi): t00=t00-RR(2.0*pi) while(t11>2*pi): t11=t11-RR(2.0*pi) xc=CC(c).real() yc=CC(c).imag() L0 = [[RR(r*cos(t00+i*(t11-t00)/num_pts))+xc,RR(r*sin(t00+i*(t11-t00)/num_pts))+yc] for i in range(0 ,num_pts)] ca=line(L0) return ca
def _geodesic_between_two_points_d(x1, y1, x2, y2, z0=I): r""" Geodesic path between two points represented in the unit disc by the map w = (z-I)/(z+I) INPUTS: - ''(x1,y1)'' -- starting point (0<y1<=infinity) - ''(x2,y2)'' -- ending point (0<y2<=infinity) - ''z0'' -- (default I) the point in the upper corresponding to the point 0 in the disc. I.e. the transform is w -> (z-I)/(z+I) OUTPUT: - ''ca'' -- a polygonal approximation of a circular arc centered at c and radius r, starting at t0 and ending at t1 EXAMPLES:: sage: l=_geodesic_between_two_points_d(0.1,0.2,0.0,0.5) """ pi = RR.pi() from sage.plot.plot import line from sage.functions.trig import (cos, sin) # First compute the points if (y1 < 0 or y2 < 0): raise ValueError, "Need points in the upper half-plane! Got y1=%s, y2=%s" % ( y1, y2) if (y1 == infinity): P1 = CC(1) else: P1 = CC((x1 + I * y1 - z0) / (x1 + I * y1 - z0.conjugate())) if (y2 == infinity): P2 = CC(1) else: P2 = CC((x2 + I * y2 - z0) / (x2 + I * y2 - z0.conjugate())) # First find the endpoints of the completed geodesic in D if (x1 == x2): a = CC((x1 - z0) / (x1 - z0.conjugate())) b = CC(1) else: c = RR(y1**2 - y2**2 + x1**2 - x2**2) / RR(2 * (x1 - x2)) r = RR(sqrt(y1**2 + (x1 - c)**2)) a = c - r b = c + r a = CC((a - z0) / (a - z0.conjugate())) b = CC((b - z0) / (b - z0.conjugate())) if (abs(a + b) < 1E-10): # On a diagonal return line([[P1.real(), P1.imag()], [P2.real(), P2.imag()]]) th_a = a.argument() th_b = b.argument() # Compute the center of the circle in the disc model if (min(abs(b - 1), abs(b + 1)) < 1E-10 and min(abs(a - 1), abs(a + 1)) > 1E-10): c = b + I * (1 - b * cos(th_a)) / sin(th_a) elif (min(abs(b - 1), abs(b + 1)) > 1E-10 and min(abs(a - 1), abs(a + 1)) < 1E-10): c = a + I * (1 - a * cos(th_b)) / RR(sin(th_b)) else: cx = (sin(th_b) - sin(th_a)) / sin(th_b - th_a) c = cx + I * (1 - cx * cos(th_b)) / RR(sin(th_b)) # First find the endpoints of the completed geodesic r = abs(c - a) t1 = CC(P1 - c).argument() t2 = CC(P2 - c).argument() #print "t1,t2=",t1,t2 return _circ_arc(t1, t2, c, r)
def draw_fundamental_domain(N, group='Gamma0', model="H", axes=None, filename=None, **kwds): r""" Draw fundamental domain INPUT: - ''model'' -- (default ''H'') - ''H'' -- Upper halfplane - ''D'' -- Disk model - ''filename''-- filename to print to - ''**kwds''-- additional arguments to matplotlib - ''axes'' -- set geometry of output =[x0,x1,y0,y1] -- restrict figure to [x0,x1]x[y0,y1] EXAMPLES:: sage: G=MySubgroup(Gamma0(3)) sage: G.draw_fundamental_domain() """ G = eval(group + '(' + str(N) + ')') #print G name = "$" + latex(G) + "$" ## need a "nice" set of coset representatives to draw a connected fundamental domain. Only implemented for Gamma_0(N) coset_reps = nice_coset_reps(G) if (model == "D"): g = draw_funddom_d(coset_reps, format, I) else: g = draw_funddom(coset_reps, format) if (axes <> None): [x0, x1, y0, y1] = axes elif (model == "D"): x0 = -1 x1 = 1 y0 = -1.1 y1 = 1 else: # find the width of the fundamental domain w = 0 #self.cusp_width(Cusp(Infinity)) wmin = 0 wmax = 1 max_x = RR(0.55) rho = CC(exp(2 * pi * I / 3)) for V in coset_reps: ## we also compare the real parts of where rho and infinity are mapped r1 = (V.acton(rho)).real() if (V[1, 0] <> 0): inf1 = RR(V[0, 0] / V[1, 0]) else: inf1 = 0 if (V[1, 0] == 0 and V[0, 0] == 1): if (V[0, 1] > wmax): wmax = V[0, 1] if (V[0, 1] < wmin): wmin = V[0, 1] if (max(r1, inf1) > max_x): max_x = max(r1, inf1) #print "wmin,wmax=",wmin,wmax #x0=-1; x1=1; y0=-0.2; y1=1.5 x0 = RR(-max_x) x1 = RR(max_x) y0 = RR(-0.15) y1 = RR(1.5) ## Draw the axes manually (since can't figure out how to do it automatically) ax = line([[x0, 0.0], [x1, 0.0]], color='black') #ax = ax + line([[0.0,y0],[0.0,y1]],color='black') ## ticks ax = ax + line([[-0.5, -0.01], [-0.5, 0.01]], color='black') ax = ax + line([[0.5, -0.01], [0.5, 0.01]], color='black') g = g + ax if model == "H": t = text(name, (0, -0.1), fontsize=16, color='black') else: t = text(name, (0, -1.1), fontsize=16, color='black') g = g + t g.set_aspect_ratio(1) g.set_axes_range(x0, x1, y0, y1) g.axes(False) if (filename <> None): fig = g.matplotlib() fig.set_canvas(FigureCanvasAgg(fig)) axes = fig.get_axes()[0] axes.minorticks_off() axes.set_yticks([]) fig.savefig(filename, **kwds) else: return g
def rhf(b_1_sqr, log_vol, dim): log_b_sqr = log(b_1_sqr) log_rhf = (0.5 * log_b_sqr - log_vol / dim) / dim return exp(log_rhf) profile_bsw18 = [M.get_r(i, i) for i in range(M.d)] profile_cn11 = [M.get_r(i, i) for i in range(M.d)] rhfs_bsw18 = [] rhfs_cn11 = [] rhfs_bsw18.append((0, rhf(profile_bsw18[0], log_vol, M.d))) rhfs_cn11.append((0, rhf(profile_cn11[0], log_vol, M.d))) for tour in range(1, max_loops + 1): profile_bsw18 = BSW18.simulate( profile_bsw18, BKZ.Param(block_size=block_size, max_loops=1))[0] profile_cn11 = CN11_simulate(profile_cn11, BKZ.Param(block_size=block_size, max_loops=1))[0] rhfs_bsw18.append((tour, rhf(profile_bsw18[0], log_vol, M.d))) rhfs_cn11.append((tour, rhf(profile_cn11[0], log_vol, M.d))) g = line(rhfs_bsw18, legend_label="BSW18", linestyle="dashed", title=f"dim = {M.d}, beta = {block_size}", axes_labels=["tours", "rhf"]) g += line(rhfs_cn11, legend_label="CN11", linestyle="dashed", color="red") save(g, f"rhf-{M.d}-{block_size}.png", dpi=150)
def draw_fundamental_domain(N,group='Gamma0',model="H",axes=None,filename=None,**kwds): r""" Draw fundamental domain INPUT: - ''model'' -- (default ''H'') - ''H'' -- Upper halfplane - ''D'' -- Disk model - ''filename''-- filename to print to - ''**kwds''-- additional arguments to matplotlib - ''axes'' -- set geometry of output =[x0,x1,y0,y1] -- restrict figure to [x0,x1]x[y0,y1] EXAMPLES:: sage: G=MySubgroup(Gamma0(3)) sage: G.draw_fundamental_domain() """ G=eval(group+'('+str(N)+')') #print G name ="$"+latex(G)+"$" ## need a "nice" set of coset representatives to draw a connected fundamental domain. Only implemented for Gamma_0(N) coset_reps = nice_coset_reps(G) if(model=="D"): g=draw_funddom_d(coset_reps,format,I) else: g=draw_funddom(coset_reps,format) if(axes<>None): [x0,x1,y0,y1]=axes elif(model=="D"): x0=-1 ; x1=1 ; y0=-1.1 ; y1=1 else: # find the width of the fundamental domain w=0 #self.cusp_width(Cusp(Infinity)) wmin=0 ; wmax=1 max_x = RR(0.55) rho = CC( exp(2*pi*I/3)) for V in coset_reps: ## we also compare the real parts of where rho and infinity are mapped r1 = (V.acton(rho)).real() if(V[1,0]<>0): inf1 = RR(V[0,0] / V[1,0]) else: inf1 = 0 if(V[1 ,0 ]==0 and V[0 ,0 ]==1 ): if(V[0 ,1 ]>wmax): wmax=V[0 ,1 ] if(V[0 ,1 ]<wmin): wmin=V[0 ,1 ] if( max(r1,inf1) > max_x): max_x = max(r1,inf1) #print "wmin,wmax=",wmin,wmax #x0=-1; x1=1; y0=-0.2; y1=1.5 x0=RR(-max_x) ; x1=RR(max_x) ; y0=RR(-0.15) ; y1=RR(1.5) ## Draw the axes manually (since can't figure out how to do it automatically) ax = line([[x0,0.0],[x1,0.0]],color='black') #ax = ax + line([[0.0,y0],[0.0,y1]],color='black') ## ticks ax = ax + line([[-0.5,-0.01],[-0.5,0.01]],color='black') ax = ax + line([[0.5,-0.01],[0.5,0.01]],color='black') g = g + ax if model=="H": t = text(name, (0, -0.1), fontsize=16, color='black') else: t = text(name, (0, -1.1), fontsize=16, color='black') g = g + t g.set_aspect_ratio(1) g.set_axes_range(x0,x1,y0,y1) g.axes(False) if(filename<>None): fig = g.matplotlib() fig.set_canvas(FigureCanvasAgg(fig)) axes = fig.get_axes()[0] axes.minorticks_off() axes.set_yticks([]) fig.savefig(filename,**kwds) else: return g
def draw_fundamental_domain(N, group="Gamma0", model="H", axes=None, filename=None, **kwds): r""" Draw fundamental domain INPUT: - ''model'' -- (default ''H'') = ''H'' -- Upper halfplane = ''D'' -- Disk model - ''filename''-- filename to print to - ''**kwds''-- additional arguments to matplotlib - ''axes'' -- set geometry of output =[x0,x1,y0,y1] -- restrict figure to [x0,x1]x[y0,y1] EXAMPLES:: sage: G=MySubgroup(Gamma0(3)) sage: G.draw_fundamental_domain() """ if group.strip() == "Gamma0": G = Gamma0(N) elif group.strip() == "Gamma1": G = Gamma1(N) elif group.strip() == "Gamma": G = Gamma(N) else: raise ValueError('group must be one of: "Gamma0", "Gamma1", "Gamma"') s = "$" + latex(G) + "$" s = s.replace("mbox", "mathrm") s = s.replace("Bold", "mathbb") name = s # name ="$\mbox{SL}_{2}(\mathbb{Z})$" # need a "nice" set of coset representatives to draw a connected # fundamental domain. Only implemented for Gamma_0(N) coset_reps = nice_coset_reps(G) # if(group=='Gamma0'): # else: # coset_reps = list(G.coset_reps()) from matplotlib.backends.backend_agg import FigureCanvasAgg if model == "D": g = _draw_funddom_d(coset_reps, format, I) else: g = _draw_funddom(coset_reps, format) if axes is not None: [x0, x1, y0, y1] = axes elif model == "D": x0 = -1 x1 = 1 y0 = -1.1 y1 = 1 else: # find the width of the fundamental domain # w = 0 # self.cusp_width(Cusp(Infinity)) FIXME: w is never used wmin = 0 wmax = 1 max_x = RR(0.55) rho = CC(exp(2 * pi * I / 3)) for V in coset_reps: ## we also compare the real parts of where rho and infinity are mapped r1 = (V.acton(rho)).real() if V[1, 0] != 0: inf1 = RR(V[0, 0] / V[1, 0]) else: inf1 = 0 if V[1, 0] == 0 and V[0, 0] == 1: if V[0, 1] > wmax: wmax = V[0, 1] if V[0, 1] < wmin: wmin = V[0, 1] if max(r1, inf1) > max_x: max_x = max(r1, inf1) logging.debug("wmin,wmax=%s,%s" % (wmin, wmax)) # x0=-1; x1=1; y0=-0.2; y1=1.5 x0 = RR(-max_x) x1 = RR(max_x) y0 = RR(-0.15) y1 = RR(1.5) ## Draw the axes manually (since can't figure out how to do it automatically) ax = line([[x0, 0.0], [x1, 0.0]], color="black") # ax = ax + line([[0.0,y0],[0.0,y1]],color='black') ## ticks ax = ax + line([[-0.5, -0.01], [-0.5, 0.01]], color="black") ax = ax + line([[0.5, -0.01], [0.5, 0.01]], color="black") g = g + ax if model == "H": t = text(name, (0, -0.1), fontsize=16, color="black") t = t + text("$ -\\frac{1}{2} $", (-0.5, -0.1), fontsize=12, color="black") t = t + text("$ \\frac{1}{2} $", (0.5, -0.1), fontsize=12, color="black") else: t = text(name, (0, -1.1), fontsize=16, color="black") g = g + t g.set_aspect_ratio(1) g.set_axes_range(x0, x1, y0, y1) g.axes(False) if filename is not None: fig = g.matplotlib() fig.set_canvas(FigureCanvasAgg(fig)) axes = fig.get_axes()[0] axes.minorticks_off() axes.set_yticks([]) fig.savefig(filename, **kwds) else: return g
# n_halfs, block_size, max_loops = 75, 60, 50 # n_halfs, block_size, max_loops = 75, 60, 20000 # generate lattice instance FPLLL.set_random_seed(1337) q = 2**30 mat = IntegerMatrix.random(2 * n_halfs, "qary", q=q, k=n_halfs) A = LLL.reduction(mat) M = GSO.Mat(A) M.update_gso() cn11 = CN11_simulate(M, BKZ.Param(block_size=block_size, max_loops=max_loops)) bsw18 = BSW18.simulate(M, BKZ.Param(block_size=block_size, max_loops=max_loops)) og = og.simulate(M, BKZ.Param(block_size=block_size, max_loops=max_loops)) g = line([(i, log(cn11[0][i])/2 - log(q)/2) for i in range(len(cn11[0]))]) \ + line([(i, log(bsw18[0][i])/2 - log(q)/2) for i in range(len(bsw18[0]))], color='red', thickness=2) \ + line([(i, log(og[0][i])/2 - log(q)/2) for i in range(len(og[0]))], color='green') save(g, "test.png", dpi=150) log_vol_cn11 = sum(map(lambda x: log(x) / 2, cn11[0])) log_vol_bsw18 = sum(map(lambda x: log(x) / 2, bsw18[0])) log_vol_og = sum(map(lambda x: log(x) / 2, og[0])) smat = matrix(M.d, M.d) mat.to_matrix(smat) vol = abs(smat.determinant()) log_vol = log(vol).n() print("log vol %.6f" % log_vol) print(" cn11 %.6f" % log_vol_cn11)
def _draw_funddom(coset_reps, format="S"): r""" Draw a fundamental domain for G. INPUT: - ``format`` -- (default 'Disp') How to present the f.d. - ``S`` -- Display directly on the screen EXAMPLES:: sage: G=MySubgroup(Gamma0(3)) sage: G._draw_funddom() """ pi = RR.pi() pi_3 = pi / RR(3.0) from sage.plot.plot import (Graphics, line) from sage.functions.trig import (cos, sin) g = Graphics() x1 = RR(-0.5) y1 = RR(sqrt(3) / 2) x2 = RR(0.5) y2 = RR(sqrt(3) / 2) xmax = RR(20.0) l1 = line([[x1, y1], [x1, xmax]]) l2 = line([[x2, y2], [x2, xmax]]) l3 = line([[x2, xmax], [x1, xmax]]) # This is added to make a closed contour c0 = _circ_arc(RR(pi / 3.0), RR(2.0 * pi) / RR(3.0), 0, 1, 100) tri = c0 + l1 + l3 + 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 = RR(-a) b = RR(-b) c = RR(-c) d = RR(-d) else: a = RR(a) b = RR(b) c = RR(c) d = RR(d) if (c == 0): # then this is easier L0 = [[cos(pi_3 * RR(i / 100.0)) + b, sin(pi_3 * RR(i / 100.0))] for i in range(100, 201)] L1 = [[x1 + b, y1], [x1 + b, xmax]] L2 = [[x2 + b, y2], [x2 + b, xmax]] L3 = [[x2 + b, xmax], [x1 + b, xmax]] c0 = line(L0) l1 = line(L1) l2 = line(L2) l3 = line(L3) tri = c0 + l1 + l3 + 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(x1_t, y1_t, x2_t, y2_t) c1 = _geodesic_between_two_points(x1_t, y1_t, inf_t, 0.) c2 = _geodesic_between_two_points(x2_t, y2_t, inf_t, 0.0) tri = c0 + c1 + c2 g = g + tri return g
def draw_fundamental_domain(N, group='Gamma0', model="H", axes=None, filename=None, **kwds): r""" Draw fundamental domain INPUT: - ''model'' -- (default ''H'') = ''H'' -- Upper halfplane = ''D'' -- Disk model - ''filename''-- filename to print to - ''**kwds''-- additional arguments to matplotlib - ''axes'' -- set geometry of output =[x0,x1,y0,y1] -- restrict figure to [x0,x1]x[y0,y1] EXAMPLES:: sage: G=MySubgroup(Gamma0(3)) sage: G.draw_fundamental_domain() """ if group.strip() == 'Gamma0': G = Gamma0(N) elif group.strip() == 'Gamma1': G = Gamma1(N) elif group.strip() == 'Gamma': G = Gamma(N) else: raise ValueError('group must be one of: "Gamma0", "Gamma1", "Gamma"') s = "$" + latex(G) + "$" s = s.replace("mbox", "mathrm") s = s.replace("Bold", "mathbb") name = s # name ="$\mbox{SL}_{2}(\mathbb{Z})$" # need a "nice" set of coset representatives to draw a connected # fundamental domain. Only implemented for Gamma_0(N) coset_reps = nice_coset_reps(G) # if(group=='Gamma0'): # else: # coset_reps = list(G.coset_reps()) from matplotlib.backends.backend_agg import FigureCanvasAgg if (model == "D"): g = _draw_funddom_d(coset_reps, format, I) else: g = _draw_funddom(coset_reps, format) if (axes is not None): [x0, x1, y0, y1] = axes elif (model == "D"): x0 = -1 x1 = 1 y0 = -1.1 y1 = 1 else: # find the width of the fundamental domain # w = 0 # self.cusp_width(Cusp(Infinity)) FIXME: w is never used wmin = 0 wmax = 1 max_x = RR(0.55) rho = CC(exp(2 * pi * I / 3)) for V in coset_reps: ## we also compare the real parts of where rho and infinity are mapped r1 = (V.acton(rho)).real() if (V[1, 0] != 0): inf1 = RR(V[0, 0] / V[1, 0]) else: inf1 = 0 if (V[1, 0] == 0 and V[0, 0] == 1): if (V[0, 1] > wmax): wmax = V[0, 1] if (V[0, 1] < wmin): wmin = V[0, 1] if (max(r1, inf1) > max_x): max_x = max(r1, inf1) logging.debug("wmin,wmax=%s,%s" % (wmin, wmax)) # x0=-1; x1=1; y0=-0.2; y1=1.5 x0 = RR(-max_x) x1 = RR(max_x) y0 = RR(-0.15) y1 = RR(1.5) ## Draw the axes manually (since can't figure out how to do it automatically) ax = line([[x0, 0.0], [x1, 0.0]], color='black') # ax = ax + line([[0.0,y0],[0.0,y1]],color='black') ## ticks ax = ax + line([[-0.5, -0.01], [-0.5, 0.01]], color='black') ax = ax + line([[0.5, -0.01], [0.5, 0.01]], color='black') g = g + ax if model == "H": t = text(name, (0, -0.1), fontsize=16, color='black') t = t + text( "$ -\\frac{1}{2} $", (-0.5, -0.1), fontsize=12, color='black') t = t + text( "$ \\frac{1}{2} $", (0.5, -0.1), fontsize=12, color='black') else: t = text(name, (0, -1.1), fontsize=16, color='black') g = g + t g.set_aspect_ratio(1) g.set_axes_range(x0, x1, y0, y1) g.axes(False) if (filename is not None): fig = g.matplotlib() fig.set_canvas(FigureCanvasAgg(fig)) axes = fig.get_axes()[0] axes.minorticks_off() axes.set_yticks([]) fig.savefig(filename, **kwds) else: return g
def _geodesic_between_two_points_d(x1,y1,x2,y2,z0=I): r""" Geodesic path between two points represented in the unit disc by the map w = (z-I)/(z+I) INPUTS: - ''(x1,y1)'' -- starting point (0<y1<=infinity) - ''(x2,y2)'' -- ending point (0<y2<=infinity) - ''z0'' -- (default I) the point in the upper corresponding to the point 0 in the disc. I.e. the transform is w -> (z-I)/(z+I) OUTPUT: - ''ca'' -- a polygonal approximation of a circular arc centered at c and radius r, starting at t0 and ending at t1 EXAMPLES:: sage: l=_geodesic_between_two_points_d(0.1,0.2,0.0,0.5) """ pi=RR.pi() from sage.plot.plot import line from sage.functions.trig import (cos,sin) # First compute the points if(y1<0 or y2<0 ): raise ValueError,"Need points in the upper half-plane! Got y1=%s, y2=%s" %(y1,y2) if(y1==infinity): P1=CC(1 ) else: P1=CC((x1+I*y1-z0)/(x1+I*y1-z0.conjugate())) if(y2==infinity): P2=CC(1 ) else: P2=CC((x2+I*y2-z0)/(x2+I*y2-z0.conjugate())) # First find the endpoints of the completed geodesic in D if(x1==x2): a=CC((x1-z0)/(x1-z0.conjugate())) b=CC(1 ) else: c=RR(y1**2 -y2**2 +x1**2 -x2**2 )/RR(2 *(x1-x2)) r=RR(sqrt(y1**2 +(x1-c)**2 )) a=c-r b=c+r a=CC((a-z0)/(a-z0.conjugate())) b=CC((b-z0)/(b-z0.conjugate())) if( abs(a+b) < 1E-10 ): # On a diagonal return line([[P1.real(),P1.imag()],[P2.real(),P2.imag()]]) th_a=a.argument() th_b=b.argument() # Compute the center of the circle in the disc model if( min(abs(b-1 ),abs(b+1 ))< 1E-10 and min(abs(a-1 ),abs(a+1 ))>1E-10 ): c=b+I*(1 -b*cos(th_a))/sin(th_a) elif( min(abs(b-1 ),abs(b+1 ))> 1E-10 and min(abs(a-1 ),abs(a+1 ))<1E-10 ): c=a+I*(1 -a*cos(th_b))/RR(sin(th_b)) else: cx=(sin(th_b)-sin(th_a))/sin(th_b-th_a) c=cx+I*(1 -cx*cos(th_b))/RR(sin(th_b)) # First find the endpoints of the completed geodesic r=abs(c-a) t1=CC(P1-c).argument() t2=CC(P2-c).argument() #print "t1,t2=",t1,t2 return _circ_arc(t1,t2,c,r)
from sage.all import log, exp from sage.all import line, save, load, identity_matrix, matrix from fpylll import IntegerMatrix, GSO, LLL, FPLLL, BKZ from fpylll.tools.bkz_simulator import simulate as CN11_simulate import BSW18 # n_halfs, block_size, max_loops = 50, 45, 2000 n_halfs, block_size, max_loops = 90, 170, 60 # n_halfs, block_size, max_loops = 75, 60, 50 # n_halfs, block_size, max_loops = 75, 60, 20000 # generate lattice instance FPLLL.set_random_seed(1337) q = 2**30 mat = IntegerMatrix.random(2 * n_halfs, "qary", q=q, k=n_halfs) A = LLL.reduction(mat) M = GSO.Mat(A) M.update_gso() cn11 = CN11_simulate(M, BKZ.Param(block_size=block_size, max_loops=max_loops)) bsw18 = BSW18.simulate(M, BKZ.Param(block_size=block_size, max_loops=max_loops)) g = line([(i, log(cn11[0][i])/2 - log(q)/2) for i in range(len(cn11[0]))]) \ + line([(i, log(bsw18[0][i])/2 - log(q)/2) for i in range(len(bsw18[0]))], color='red') save(g, "test.png", dpi=150)