From: Andrew P <gr...@gm...> - 2005-09-28 16:12:07
|
Awesome. Thank you so much. This was the obvious bit I was missing. I just needed a nudge towards blit. I'm sure this is all pretty obvious to anybody whose programmed with a GUI before, or at least drawn anything out in one. I already have a generator function, which returns the next iteration ad nauseum. I managed to build a window down from the top row with one drawPointList at a time, and it worked really well. But when I got to the bottom I just started scratching my head. My first algorithm looked a lot like yours. After tweaking pure Python as much as I could I ended up with: def makeArray1(firstrow): result =3D firstrow[:] result[0][w/2] =3D 1 for row in range(h-1): last =3D result[row] next =3D result[row+1] for i in range(w-1): next[i] =3D rule[4*last[i-1]+2*last[i]+last[i+1]] next[i+1] =3D rule[4*last[i]+2*last[i+1]+last[0]] return result Which gets a bit ugly because it's quite a bit faster to assign directly to an index, than to append. And pulling the row lookups out of the inner loop also speeds it up quite a bit. It's very fast with psyco (about 20x), but I suspect yours (and my first readable one) would be about the same once compiled. That was the fastest native version I came up with tho. With numpy I got within 20% or so of psycos performance, and stayed cross-platform. My iBook really appreciated this, my brain did not. I feel like I'm making excuses for my ugly numpy algorithm, which is almost entirely incomprehensible to me. I guess there's no sin in optimizing an inner loop that applies to a million elements. Especially with an iBook involved. The only other interesting tidbit was it was faster to do all that 1<<element&rule stuff than to just use a lookup table to get a 1 or 0. So numpy is just bloody fast. Or maybe array access is slow. I don't care. I'm done with that bloody algorithm :) Thanks again! Andrew On 9/28/05, Alex Tweedly <al...@tw...> wrote: > > Andrew P wrote: > > > Hi Alex, > > > > Let me explain a little more what I'm trying to do. First off. here > > is a screenshot of what I did today: > > > Cool. Thanks Andrew - I have a much better idea now. > > Here's what I believe (tell me if I'm wrong), followed by what I > conclude from those beliefs. > > You're doing CA where each row depends on the previous row (or perhaps > in the future on previous rows). > Once a cell's value has been determined, it never changes. > You need to scroll as the cells are determined - not backwards and > forwards under user control. > > From that I conclude: > > You should calculate one row at a time, draw it, and then move on to the > next one. > You should use one one-dim arrays (lists) to hold the previous and > current rows > You should scroll by using bit-blits, not by re-drawing. > > so (after the initial phase to fill the window), what you'll do in each > cycle through the loop is > > calculate the next line > scroll the current window up by one line > draw in newly calculated row at bottom of window. > > > Here's the core part of a sample program to do that .... no doubt it > could be improved, but I kept it as simple so I could figure it out. I > use a button called "Change" so I can single-step through the process, > and when I run with the timer, I simply call the single-step function - > could certainly be cleaned up :-) > > (And for the boundary condition at start/end of the list, I used a > try... except ... - very lazy of me). > > > def draw_row(self, y): > > points =3D [] > > pens =3D [] > > for i in range(self.width): > > if self.cells[i]: > > points.append( (i,y) ) > > pens.append( self.basicpen ) > > self.components.bmpCanvas.drawPointList( points, pens ) > > > > > > def on_Change_mouseClick(self, event): > > if self.row =3D=3D 0: > > self.draw_row(0) > > self.row +=3D 1 > > return > > > > start =3D time.clock() > > > > if self.row >=3D self.height: > > cv =3D self.components.bmpCanvas > > cv.blit( (0,0), (self.width,self.height), cv._bufImage, (0,1)) > > cv.drawRectangleList( [ (0,self.height, self.width,1)], > > [self.whitepen]) > > y =3D self.height > > else: > > y =3D self.row > > > > cells =3D self.change(self.cells) > > self.cells =3D cells > > > > self.draw_row(y) > > self.row +=3D 1 > > > > ## print "took ", time.clock()-start > > return > > > > def on_bmpCanvas_timer(self, event): > > self.on_Change_mouseClick(event) > > return > > > > > > def change(self, cells): > > new =3D [] > > rule =3D [ 0, 1, 1, 0, 1, 0, 0, 1 ] > > > > for i in range(len(cells)): > > try: > > newval =3D 4*cells[i-1] + 2*cells[i] + cells[i+1] > > except: > > newval =3D 0 > > new.append( rule[newval] ) > > return new > > > If you want the entire sample, let me know .... > > -- > Alex Tweedly http://www.tweedly.net > > > > -- > No virus found in this outgoing message. > Checked by AVG Anti-Virus. > Version: 7.0.344 / Virus Database: 267.11.6/111 - Release Date: 23/09/200= 5 > > |