Upcoming SlideShare
×

# Making of-the-logistic-map-bifurcation-diagram

1,896 views

Published on

ChiPy presentation, June 12 2014. Speeding up logistic map bifurcation diagram using PyPy, C extension, and Cython.

Published in: Software
2 Likes
Statistics
Notes
• Full Name
Comment goes here.

Are you sure you want to Yes No
• Be the first to comment

Views
Total views
1,896
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
15
0
Likes
2
Embeds 0
No embeds

No notes for slide

### Making of-the-logistic-map-bifurcation-diagram

1. 1. Making of: The logistic map bifurcation diagram BradMartsberger
2. 2. What is this talk about? Makingaprettypicture Squeezingperformance outof python PyPy, Cython, C extensions With atoyphysics model(chaos!)
3. 3. Fun with fractals
4. 4. Cool, but... Where did that come from? Can you show me some python already?
5. 5. The logistic map Map avalue, x, from [0, 1] to [0, 1] accordingto: r *x *(1 -x) Let's play... x=0.25 r=2.5 forjinrange(limit): print"x:",x x=r*x*(1-x)
6. 6. What do we need to make that sweet graph? Python Matplotlib Patience ... lots of patience
7. 7. Simplified version bif_diag=[[0.0]*height]*width forkinrange(width): #histogramofhowfrequentlyeachpixelisvisited. h=logmap_histogram(r,x_len,x1,x2,height) #Normalizethehistogramtogofrom0to1. h=divide_list(h,1.0*max(h)) #stickitinupsidedowntotheimage bif_diag[k-1]=h[::-1] plot_bif_diag(bif_diag,plt,cm,(x1,x2),(r_lower,r_upper))
8. 8. Inner loop deflogmap_histogram(r,x_len,x1,x2,height): result=[0]*height dx=1.0*(x2-x1)/(height-1) transient=500 x=0.25 forkinxrange(transient): x=x*r*(1-x) forkinxrange(x_len): x=x*r*(1-x) incr=int((x-x1)/dx) ifincr>=0andincr<M: result[incr]+=1 returnresult
9. 9. Matplotlib bit defplot_bif_diag(bif_diag,plt,cm,xlim,rlim): width,height,=len(bif_diag),len(bif_diag[1]) to_plot=[[1-pixforpixincol]forcolinbif_diag] to_plot=map(list,zip(*to_plot)) plt.imshow(to_plot,cm.gray,clim=(0.7,1)) font={'family':'serif','size':24} plt.xlabel('r',fontdict=font) plt.ylabel('x*',fontdict=font) plt.xticks(linspace(1,N,9),['%.2g'%rforrinlinspace(rlim[0],rlim[1],9)]) plt.yticks(linspace(1,M-1,5),['%.2g'%xforxinlinspace(xlim[1],xlim[0],5)] ax=plt.gca() ax.set_position([80./(width+100.),80./(height+100.),width/(width+100.), plt.gcf().canvas.manager.window.geometry("{0}x{1}+30+30".format(width+100,height+ plt.show()
10. 10. Let's run this thing already...
11. 11. That was a little disappointing Nothorrible, buttoo slow to do some coolstuff.
12. 12. Options for doing better 0. Quitusingpython 1. PyPy 2. C extension 3. Cython 4. There are others (numpywith numexpr)
13. 13. PyPy Straightfrom pypy.org: Fast, compliantalternative implementation of the Python language (2.7.6 and 3.2.3) with severaladvantages: Speed, due to Just-In-Time compiler Takes less memory Supports anumber of third partylibraries: ctypes, django, sqlalchemy, twisted, etc. Does notrequire anychange to your code! Unfortunately, matplotlib is notsupported. Numpyis partiallysupported.
14. 14. C extensions Write functions in C thatare callable from python Pass python objects as arguments thatmustbe converted to C values Returns apython object, e.g., alist Compiled and fast Do this atleastonce
15. 15. Let's have a look staticPyObject*logmap_attractor_histogram(PyObject*self,PyObject*args){ doubler1,r2,x,x1,x2; intxxlen,rrlen,M; inttransient=500;//Shorttransientforeachr. if(!PyArg_ParseTuple(args,"ddiiddi",&r1,&r2,&rrlen,&xxlen,&x1,&x2,&M)){ returnNULL; } //Storeourhistograminanintarray,copyittoapythonlistandreturn //thelistasaPyObject* intarray[M]; PyObject*list=PyList_New(M); //Initializearraytoallzeros intj,k; for(j=0;j<M;++j){ array[j]=0; } doubler,dr,dx; intincr; //Settheamountwewillsteptogetfromr1tor2inrrlen-1steps dr=0; if(rrlen>1){dr=(r2-r1)/(rrlen-1);} //Histogrambinsize dx=(x2-x1)/(M-1); //loopoverr(perhapschangetofor(r=r1;r<=r2;r+=dr))
16. 16. Compiling to an importable module Create asetup.pyfile, e.g: fromdistutils.coreimportsetup,Extension setup(name='logmap',version='1.0', ext_modules=[Extension('logmap',['logmapmodule.c'])]) Then installit >>>pythonsetup.pyinstall And itcan be imported and called importlogmap h= logmap.attractor_histogram(...)
17. 17. Let's see it already...
18. 18. Cython Directlyfrom cython.org: Static compiler for python Makes writingC extensions for python as easyas writing python Generates C code from your python code Has the potentialto deliver the speed gains thatwe getfrom aC extension with less hassle
19. 19. How to make it work Create setup.pyfile: Build like this: Then you can importfrom logistic_map_bifurcation_diagram_cython fromdistutils.coreimportsetup fromCython.Buildimportcythonize setup( name='logmap_cython', ext_modules=cythonize("logistic_map_bifurcation_diagram_cython.pyx"), ) %>pythonsetup.pybuild_ext--in_place
20. 20. Making cython faster Cython's code generation is helped byprovidingithints in the form of type declarations deflogmap_histogram(floatr1,floatr2,intrrlen,intxxlen,floatx1,floatx2,intM) result=[0]*M cdeffloatdx dx=1.0*(x2-x1)/(M-1) transient=500 cdeffloatx cdeffloatr cdeffloatk forrinlinspace(r1,r2,rrlen): x=0.25 forkinrange(transient): x=x*r*(1-x) forkinrange(xxlen): x=x*r*(1-x) incr=int((x-x1)/dx) ifincr>=0andincr<M: result[incr]+=1 returnresult