ENUNCIADOS DEL L3feb: 1) Definir un generador 'iteref' que acepte un valor inicial 0<r<1 y vaya devolviendo los sucesivos valores f(f( …(r) …)) que resultan de iterar la función f(x) = 4 * x * (1-x). RECORDATORIO: hay que usar yield en la definición. 2) Llamando a ese generador con un valor inicial de 3 decimales, por ejemplo: g = iteref(0.234), o el que se te antoje, producir una lista 'fnr' con 200 de esos valores sucesivos, pero redondeados a 2 cifras decimales. RECORDATORIO: round , y AVISO: si no te funciona el generador, puedes hacer este código sin usarlo, claro. 3) Crear un diccionario 'frec' y guardar en él las frecuencias de los valores k/100 que aparecen en la lista 'fnr'; y producir algún output que permita ver (de manera razonablemente clara) toda esa info guardada en 'frec'. OJO: los valores van a "ser" ciertos k/100, gracias al redondeo, pero Sage no va a estar de acuerdo con eso! ??? 4) Crear algún gráfico razonable que ayude a VISUALIZAR lo que contiene el diccionario 'frec'. Si ya está terminado y listo para regalo todo lo anterior, y te sobra tiempo y ganas, piensa cómo visualizar con un gráfico el proceso de iteraciones que ha producido esos 200 valores … o mejor parte de ellos (el arranque del proceso). def iteref(r): while 0<r<1: yield r r = 4*r*(1-r) r0, N = 0.234, 200 g = iteref(r0) fnr = [round(g.next(),2) for k in range(N)] frec = {} for r in fnr: if r in frec: frec[r] += 1 else: frec[r] = 1 for r in sorted(frec.keys()): print '%3s %d '%(str(r)[-3:],frec[r]), 0.0 0.1 .23 .34 .48 .61 .73 .85 .96 7 3 3 1 3 2 3 3 2 .01 .11 .24 .35 .49 .62 .74 .86 .97 7 2 1 2 1 2 3 4 3 .02 .12 .25 .37 0.5 .63 .75 .87 .98 6 1 3 2 1 2 5 1 5 .03 .13 .26 .39 .51 .64 .76 .88 .99 2 1 1 1 1 1 4 4 4 .04 .14 .27 .41 .52 .65 .78 0.9 1.0 2 2 2 1 1 2 1 2 9 .05 .16 .28 .42 .54 .66 .79 .91 3 1 2 2 1 2 4 3 .06 .17 0.3 .43 .55 .67 0.8 .92 1 1 1 2 1 2 4 2 .07 .18 .31 .44 .57 .69 .81 .93 4 2 4 2 1 2 1 3 .08 .19 .32 .46 .59 .71 .82 .94 1 4 2 1 2 2 1 3 .09 .22 .33 .47 0.6 .72 .83 .95 3 1 1 2 1 2 1 3 s, h = 1/241, 0.025 # con una linea de "medias locales sobre intervalos" centros, medias = srange(0,1+s,s), [] for c in centros: (a,b) = (max(-.001,c-h),min(1.001,c+h)) m = sum([frec[r] for r in frec if a<=r<=b])/(b-a)/100 medias.append((c,m)) line(medias, figsize = (6,3))+ point([(r,frec[r]) for r in frec]) # VERSION SOFISTICADA: medias "ponderadas" con la función p(x)=max(0,h-|x-c|) s, h = 1/2014, 0.05 centros, medias = srange(0,1+s,s), [] w = h^2*100 # la integral de p(x)*100 dx for c in centros: # si la p(x) "se sale por un extremo", hay que corregir w if c<h or 1-c<h: dw = min((h-c)^2/2, (h-1+c)^2/2)*100 else: dw=0 m = sum([frec[r]*(h-abs(c-r)) for r in frec if abs(c-r)<=h])/(w-dw) medias.append((c,m)) gra = line(medias, figsize = (6,3), color='red') for r in frec: gra += line([(r,0),(r,frec[r])], thickness=2) # y alternativa a los puntos show(gra) var('x') r, f = r0, 4*x*(1-x) tray = [(r,r)] graf = plot(x,(x,0,1),linestyle='dotted',figsize=(4,3)) + plot(f,(x,0,1)) + point(tray,pointsize=40) for k in range(33): ant, r = r, f(x=r) tray += [(ant,r),(r,r)] graf + line(tray,color='green')+ point(tray[1::2],color='red',pointsize=20) fesp = 30 N = 100*fesp densidad = fesp/sqrt(x*(1-x))/pi frec = {} for k in range(N): r = round(g.next(),2) if r in frec: frec[r] += 1 else: frec[r] = 1 gra = plot(densidad, (x,.005,.995), figsize = (7,3), color='red') for r in frec: gra += line([(r,0),(r,frec[r])], thickness=2) # y alternativa a los puntos show(gra) LO DE HOY, L 10 feb %time is_prime(2^(2^13)+1) False CPU time: 0.46 s, Wall time: 0.46 s time is_prime(2^(2^13)+1) False Time: CPU 0.46 s, Wall: 0.46 s t0 = cputime() print t0 print is_prime(2^(2^13)+1), cputime(t0) 4.145368 False 0.458931 Mis sugerencias: aunque hay tantos variados recursos para "medir y comparar tiempos", limitarse a usar %time (en 1a.linea de cada cuadro y sin añadir NADA en ella), si se quiere simplemente comparar la ejecución de dos maneras de hacer lo mismo; t0 = cputime() for ... : "tarea k", que vaya guardado sucesivos valores 'cputime(t0)' si se quiere observar el crecimiento del tiempo respecto de un parámetro, y en ese caso, dos consejos: A) REPETIR el experimento y sacar medias de tiempos B) usar escalas log cuando convenga (para "descubrir" crecimientos polinomiales) EJEMPLO: def es_primo(k): return k>1 and all(k%j!=0 for j in range(2,k)) t0 = cputime() def cumultime(f,n0,N,s=1): reg = [] for k in range(n0,N,s): a = f(k) reg.append((k,1000*cputime(t0))) return reg N, rep = 4000, 40 repes = [] for repe in range(rep): t0 = cputime() reg = cumultime(es_primo,2,N) repes.append(vector([r[1] for r in reg])) line(zip(range(2,N),sum(repes)/rep), figsize=(6,3)) logmeans = [log(m,10) for m in sum(repes)/rep] logk = [log(k,10) for k in range(2,N)] loglogs = zip(logk,logmeans)[100:] line(loglogs, figsize=(6,3)) print (loglogs[-1][1]-loglogs[N/2][1])/(loglogs[-1][0]-loglogs[N/2][0]).n(17) 1.727