Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!cs.utexas.edu!wuarchive!udel!rochester!pt.cs.cmu.edu!madrid.mt.cs.cmu.edu!toad From: toad@CS.CMU.EDU (Todd Kaufmann) Newsgroups: comp.theory.cell-automata Subject: Re: cell automata for BZ reaction Message-ID: Date: 27 Sep 90 14:03:25 GMT References: <368@goya.dit.upm.es> Sender: toad@madrid.mt.cs.cmu.edu Organization: Center for Machine Translation, Carnegie Mellon University Lines: 141 In-reply-to: conc_c@greco.dit.upm.es's message of 26 Sep 90 16:10:20 GMT In article <368@goya.dit.upm.es> conc_c@greco.dit.upm.es writes: I'm interested in simulating chemical waves produced by Belusov-Zhabotinsky reaction with a cell automata. I read something about this in the section "computer games" of Oct 88 Scientific American issue. Can anyone provide references or source code? Please, email me. Thanks in advance! I think it was September '88, because I wrote the following before October. However, soon after there was a Mac version available that came out on the net, and I played with that enough to amuse my self. Since this is two years old and I only played with it for a couple hours, I don't remember much more besides the fact that I had this code. Below is the algorithm, an implementation in Common Lisp (compromise on simplicity and efficiency), and some sample forms to show how the code is used. There are also sample values for k1, k2, and g, whatever they are. I suggest finding the article for more info. Enjoy, -todd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; -*- Mode: Lisp; Package: CELLS -*- (in-package "CELLS") ;;; hodge podge simulator. See Sci Am, ~sept 88. ;;; tk 4sept88 #| for each cell if state=0 ("healthy") then new state = [A/k1] + [B/k2] where A is the number of "infected" neighbors B is the number of "ill" neighbors k1 and k2 are arbitrary constants; the authors used 2 and 3, but 2 and 4 would be better for obvious reasons! if state=MAX ("ill") then new state = 0 else ("infected") new state = [S/A] + g where S is the sum of the states of the neighbors A is the number of infected neighbors g is an arbitrary constant |# (defun hp-1gen (array k1 k2 g max new-array) "hodge podge 1 generation on inner indexes of array. edge ignored." (macrolet ((healthy-p (num) `(zerop ,num)) (health-test (x y) `(progn (cond ((>= (aref array ,x ,y) max) (incf sick)) ((not (healthy-p (aref array ,x ,y))) (incf infected)) ) (incf neighbor-sum (aref array ,x ,y))))) (let ((m (1- (array-dimension array 0))) (n (1- (array-dimension array 1))) sum state neighbor-sum) (dotimes (j n) (unless (zerop j) (setf j-1 (1- j) j+1 (1+ j) i-1 -1 i+1 1) (dotimes (i m) (unless (zerop i) (setf sick 0 infected 0 neighbor-sum 0) (health-test i-1 j-1) (health-test i-1 j) (health-test i-1 j+1) (health-test i j-1) (setf state (aref array i j)) (health-test i j+1) (health-test i+1 j-1) (health-test i+1 j) (health-test i+1 j+1) (cond ((healthy-p state) (setf (aref new-array i j) (+ (floor sick k1) (floor infected k2)))) ((>= state max) (setf (aref new-array i j) 0)) (t ; infected (setf (aref new-array i j) (+ (floor neighbor-sum infected) g))))) (setf i-1 i) (incf i+1))) ))) ) (defun pr (array) (terpri) (dotimes (j (array-dimension array 0)) (dotimes (i (array-dimension array 1)) (format t "~2d" (aref array j i))) (terpri)) (values)) (defun ran-array (array) (dotimes (j (array-dimension array 0)) (dotimes (i (array-dimension array 1)) (setf (aref array j i) (random 8))))) (setf a1 (make-array '(10 10) :initial-contents '((0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 0 0 0) (0 1 1 1 1 1 1 1 1 0) (0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 2 0 0 0 0))) a2 (make-array '(10 10) :initial-element 0)) (dotimes (i 30) (hp-1gen a1 2 3 1 9 a2) (shiftf a1 a2) (pr a1)) (setf a1 (make-array '(40 40) :initial-element 0) a2 (make-array '(40 40) :initial-element 0)) (ran-array a1)