﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-为了遗忘的记录-随笔分类-interest</title><link>http://www.cnitblog.com/Raistlin/category/1571.html</link><description>Think!</description><language>zh-cn</language><lastBuildDate>Fri, 07 Oct 2011 05:20:34 GMT</lastBuildDate><pubDate>Fri, 07 Oct 2011 05:20:34 GMT</pubDate><ttl>60</ttl><item><title>LifeApplet 阅读笔记</title><link>http://www.cnitblog.com/Raistlin/archive/2005/08/11/1479.html</link><dc:creator>Raistlin</dc:creator><author>Raistlin</author><pubDate>Thu, 11 Aug 2005 09:32:00 GMT</pubDate><guid>http://www.cnitblog.com/Raistlin/archive/2005/08/11/1479.html</guid><wfw:comment>http://www.cnitblog.com/Raistlin/comments/1479.html</wfw:comment><comments>http://www.cnitblog.com/Raistlin/archive/2005/08/11/1479.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/Raistlin/comments/commentRss/1479.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/Raistlin/services/trackbacks/1479.html</trackback:ping><description><![CDATA[<P>关于“生命”游戏<A href="http://www.cnitblog.com/raistlin/archive/2005/07/13/922.html">由此进</A>。<BR>关于LifeApplet<A href="http://www.cnitblog.com/raistlin/archive/2005/07/22/1099.html">由此进</A>，源文件<A href="http://www.cnitblog.com/Files/Raistlin/lifeapplet.rar">下载</A>。<BR><BR>本来想自己用wtl写个CA(细胞自动机)程序，阅读了LifeApplet后打消了念头。写这篇笔记像初中时一个月语文作业没写最后滥竽充数几篇交上去，算是给自己一个交待。</P>
<P>怎么写一个CA程序和想写怎样的一个CA程序有关。刚看完《上帝与新物理学》，我按照书上的规则和图案写了一个世界只有20*20大小的CA，细胞的运算是一个个计算的，计算一代就刷新显示一次，一个细胞用一个字节来保存，可以原谅的是我当时连规则都不清楚，目的只是验证一下规则。</P>
<P>看了Alan Hensel的代码后，可能大部分写过CA程序的人都会觉得汗颜。-_-|||。体验过Alan Hensel 的LifeApplet的人就会看到:他的世界真大，实际上有2^20 * 2^20个像素；速度真快，可以设置fps(每秒刷新次数)，Generations/Frame(每次刷新间隔生产多少代)，如果设置为warp，CPU就会撒开腿跑起来...还可以设置规则，CA的规则不止Conway的那个，其它的也很有趣。</P>
<P>数据结构：<BR>LifeCell:<BR>Alan Hensel将世界分成一个个16*16的单元，用LifeCell类表示。每个LifeCell包含两个数组表示 p[]，q[] = new short[16]，总共16*16 bits，表示16*16个细胞。并且在这个数组中按照一种奇怪的方式来排列，比如LifeCell中坐标为(1,1)的点在数组中的位置是65(见LifeCell文件)，代表这个点的bit就在p[6](和q[6])的<STRONG>左起</STRONG>第5位。为什么要这么表示？我想是作者为了以后unroll算法的方便。他究竟怎么得出这个方法的，我不知道。。</P>
<P>每个LifeCell需要两个数组是因为CA的算法要求的运算必须是并行的。所以只能p生成q,q生成p，没什么好说的。</P>
<P>每个LifeCell保存了相邻的东、西、南、北、东南、东北、西南、西北的LifeCell的指针。<BR>保存了上一个，下一个LifeCell的指针。所有LifeCell保存在一个链表中。<BR>保存了上一个，下一个需要显示的LifeCell的指针，用于显示。<BR>保存了一个Down的LifeCell的指针，用于hash查找。<BR>保存了坐标x,y。<BR>保存了一些状态，qstate,pstate,flags为运算和优化用的。</P>
<P>LifeHash:<BR>因为所有LifeCell都放置于一个链表。而经常要用LifeCell的坐标来查找LifeCell，比如修改某个点的状态：为了在某个点放置一个细胞，需要通过点的坐标运算出LifeCell的坐标，再通过LifeCell的坐标找到LifeCell对象。<BR>在链表中查找一个对象的运算复杂度是o(n)。n在此处最大可达2^16 * 2^16(把整个世界都占满，这也相当不容易)，所以对于一些超大的CA来说，查找起来会很浪费时间。。。所以有了LifeHash类。</P>
<P>LifeHash中保存了一个2^HASHSIZE * 2^HASHSIZE的LifeCell对象指针数组，数组中每个对象维护一个链表，坐标x,y中低HASHSIZE位的值一样的LifeCell放在这个链表中。通过x,y可以快速找到这个链表，然后用上面说到的Down指针，比较(x,y)来找到具体的LifeCell。这样理论上来讲减少了查找时间...(我算不出来，哈)。究竟用多大的HASHSIZE才好？作者的值是6，就是占用了2^12 * sizeof(int) = 16k bytes内存。</P>
<P>LifeRules：<BR>LifeRules的目的在于把用字符串表示的规则转化成一个bool[512]。<BR>比如"23/3"表示有2个或3个相邻细胞的细胞继续存活，如果一个位置旁边刚好有3个细胞，这个位置在下一步就要长出一个细胞。<BR>由于一个位置有8个相邻的位置，加上自身为9位。把9个位置排序得到一个数，总共512个。比如对于0xC8，表示西北、西有细胞，自身有细胞，根据"23/3" bool[0xC8]的值应该为true。</P>
<P>算法：<BR>为了提高效率，Alan Hensel把LifeCell中每个4*4的运算都unroll了。所以在LifeGen文件中可以看到进一步的setRules(boolean[] Rule)函数，这个函数设置了了crunch(和munch)= new short[65536]。原理和LifeRules中类似，就是不知道这个运算过程怎么得出的，作者数学肯定非常好。。</P>
<P>因为细胞的运算是以LifeCell为单元来运算的，一个单元的细胞会影响到相邻的单元。如果每次运算的时候都考虑相邻8个LifeCell的话，会造成CPU的浪费。所以在LifeGen中可以看到运算p状态和q状态时，LifeCell的位置是不一样的。从p状态生成q状态时，检查了东、南、东南方向相邻的LifeCell，生成的q状态的位置为p状态往东南各偏移一个细胞。所以如果p状态起始坐标为16x,16y，那么q状态时，起始坐标是16x+1, 16y+1(注意坐标系映射为MM，x在往东方向为正，y在往南方向为正)。在从q状态到p状态时，检查西、北、西北方向相邻的LifeCell，回到p状态的位置。</P>
<P>其中具体的运算就算了吧，反正我没看明白。看明白的地方也不知道为什么。。作者太强悍了。</P>
<P>线程：<BR>这种程序当然至少要两个线程了，一个UI线程，一个Work线程。UI线程在LifeFrame中，没做什么事，就是把事件发送给Life对象(见Life.Java)，Life收到事件后并没有马上处理，而是放到一个队列中LifeQueue。<BR>UI线程一启动，就启动了work线程。<BR>在Life的run()中，处理细胞的繁衍LifeGen.generate()，显示，然后处理LifeQueue中的事件。<BR>在LifeGen.generate()中控制生成繁衍的次数和显示的速度。<BR>为什么两个线程同时对LifeQueue操作却没有声明synchronous呢？对java不熟，不敢妄言。</P>
<P>有空还可以继续研究。先到此为止。反正作业就这么稀里糊涂交上去了。</P><img src ="http://www.cnitblog.com/Raistlin/aggbug/1479.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/Raistlin/" target="_blank">Raistlin</a> 2005-08-11 17:32 <a href="http://www.cnitblog.com/Raistlin/archive/2005/08/11/1479.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>About Conway's Game of Life Applet of Alan Hensel</title><link>http://www.cnitblog.com/Raistlin/archive/2005/07/22/1099.html</link><dc:creator>Raistlin</dc:creator><author>Raistlin</author><pubDate>Fri, 22 Jul 2005 10:15:00 GMT</pubDate><guid>http://www.cnitblog.com/Raistlin/archive/2005/07/22/1099.html</guid><wfw:comment>http://www.cnitblog.com/Raistlin/comments/1099.html</wfw:comment><comments>http://www.cnitblog.com/Raistlin/archive/2005/07/22/1099.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/Raistlin/comments/commentRss/1099.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/Raistlin/services/trackbacks/1099.html</trackback:ping><description><![CDATA[<P><A href="http://www.radicaleye.com/lifepage/java.html"><IMG alt="[A Life pattern called the puffer train]" src="http://www.radicaleye.com/lifepage/puftrn.gif"></A></P>
<P>原文:<A href="http://www.ibiblio.org/lifepatterns/lifeapplet.html">http://www.ibiblio.org/lifepatterns/lifeapplet.html<BR><BR></A>&nbsp;当前版本0.41d，更新时间2001-1-31，比0.41c版(199-1-22)上提高了些性能。新版本在计划中，只要我的空余时间允许。<BR>&nbsp;作者:Alan Hensel,</P>
<P><STRONG>简介：</STRONG><BR>认识我的人都知道我为什么写这个程序。不是为了学习Java，不是为了提高我的网站的访问量，原因很简单：<BR>我收集Life patterns，而且我喜欢展示它们</P>
<P>当然，这些patterns中的大部分是别人发现的。没人想要从这些Life patterns中获利，所以据我所知这些patterns将留给后代并被赏识，就象国际象棋一样。</P>
<P>请不要给我写信说：我喜欢你的程序，却忘记提起这些patterns。这听起来会象是恭维集邮爱好者他的邮册如何漂亮，对邮票却只字不提。我的程序只是做了它们该做的事情而已。</P>
<P><EM>计算机软件和硬件只是使用者和他的数据之间的工具</EM>。</P>
<P>这些patterns让人赞叹。如果不信，你可以自己去做一个试试。(我希望这个挑战能促成一些发现。)</P>
<P><BR><STRONG>给那些写Life程序的学生：</STRONG><BR>我没有可以给你的源代码。这里没有你找的东西。我提供了这个程序的源代码，但它们超出了计算机课程的范围。它们之所以这么复杂是因为速度优化(这样我才能运行"Breeder"或者其它更大的patterns)。当然，你可以试着读读源代码，但不要强迫自己。你写的作业应该比这个程序简单一百倍。</P>
<P><STRONG>给来这里学习Java applets的读者:</STRONG><BR>这是我第一个真正意义上的applet。最好别打算把我的代码拷贝到你的程序中。源代码就在这一页的底部，你可以免费下载，当然，你必须为它付出些东西。若非如此，这将会是一个让人相当有学习动力的applet程序。<BR><STRONG><BR>你怎么做到这么快的？</STRONG><BR>好的。没有留心的话也许你不会发现我的程序闪电一样的快。你也许没看到"Warp Speed"按钮，或者你还没用过它，或者你觉得这无所谓。这样的话你可以跳过这个部分。<BR>有人问，你究竟是怎么让它跑得这么快的？！对于这些好奇者，或者那些打算写自己的超级细胞自动机程序的人，我会解释的。</P>
<P>我倾向于把细胞自动机的优化和数据压缩联系起来。这也是一个简单的概念却需要复杂的方法。究竟什么才是最好的方案取决于数据本身。对于康威的Life，倾向于出现点状的图案。</P>
<P>对于点状分布的世界，我们应该考虑把它分割成近似大小的块。对于Life来说，4x4和8x8都是可取的。我选择了8x8，因为:刚好8比特1字节，我曾经考虑过4x4，但运行起来效果不大好。</P>
<P>并且请注意：如果pattern长大并超过了块的范围，需要引入新的块。你可以简单的线性搜索，也可折半查找，或者维护某种映射。我的方法是哈希表。这个表只是用来查找一个新块的邻居。每个已存在的块已经有它的邻居的指针，并且会被多次使用。</P>
<P>必须有高效的算法来处理这些块内部的数据，我选择一次处理块中的所有数据。在处理完整个块之前不需要跳转语句。换句话来说：所有内部循环都被unroll了，并使用了高速的查询表。</P>
<P>注意：CA(细胞自动机)程序一般性的包含了两个主要循环(加上一个显示循环)，因为CA规则要求对细胞进行并行处理，但微处理器是线性的。这意味着必须有世界的两分拷贝，这样创建下一代的时候本身的信息才不会被破坏掉。通常这两个拷贝是不对称的。这对我来说相当麻烦，因为每次我从这边取出些东西进行优化，不得不在另一边加点别的什么！几乎每次，例外的情况导致了最好的优化。特别的,需要在位操作：位移，屏蔽和重组之间折中来找一个最好的查找表。</P>
<P>有时块中的细胞会出现稳定的情况，不需要进一步处理。你可以把块从队列中移出，把它设置成“冬眠”状态，只有当邻近的块影响到它。这些块不需要占用处理器的时间，象空白的区域一样。</P>
<P>检测周期为2的振荡器并把它移出处理队列并不难。这对于Life程序是值得的，因为blinker是最常见的随机的残余物。更复杂的振荡器相对比较少见。检测并模拟滑翔机也是可能的。这些方面的优化会得到递减的效果，除非你做到极致。(如HasLife)。</P>
<P>同样，死亡状态：空的块不必马上释放并从哈希表中移走。那样会占用更多的处理器时间，尤其是当振荡器在一定空间内移进移出的时候。仅当可用内存已经很少的时候，才从死亡队列中移除最老的死亡的块。</P>
<P>当程序快到一定程度，必须考虑刷新显示的速度不需要超过人眼可以感知的速度，或者最少不需要超过显示器的刷新频率。特别是在视窗环境，显示时间会是效率的瓶颈。</P>
<P><BR><STRONG>源代码</STRONG><BR>以下是我的超级快速的Game of Life applet源代码。<BR>很抱歉这些不是百分百面向对象的。Game of Life并不适合面向对象技术。面向对象适用于你碰到的大多数问题，除了那些效率第一而且相当复杂的项目，康威的Game of Life正好属于这种情况。<BR><BR>以下是16个源文件: </P>
<P><A href="http://www.ibiblio.org/lifepatterns/src.41d/LifeButton.java" target=_top>LifeButton.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/LifeFrame.java" target=_top>LifeFrame.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/Life.java" target=_top>Life.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/LifeGUI.java" target=_top>LifeGUI.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/LifeGen.java" target=_top>LifeGen.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/LifeCell.java" target=_top>LifeCell.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/LifeHash.java" target=_top>LifeHash.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/LifeCoordinate.java" target=_top>LifeCoordinate.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/LifeRules.java" target=_top>LifeRules.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/LoadBox.java" target=_top>LoadBox.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/RuleBox.java" target=_top>RuleBox.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/SpeedBox.java" target=_top>SpeedBox.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/OptionsBox.java" target=_top>OptionsBox.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/LifeQueue.java" target=_top>LifeQueue.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/LifeCallback.java" target=_top>LifeCallback.java</A> <BR><A href="http://www.ibiblio.org/lifepatterns/src.41d/DescribeBox.java" target=_top>DescribeBox.java</A> </P><img src ="http://www.cnitblog.com/Raistlin/aggbug/1099.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/Raistlin/" target="_blank">Raistlin</a> 2005-07-22 18:15 <a href="http://www.cnitblog.com/Raistlin/archive/2005/07/22/1099.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>"生命"游戏</title><link>http://www.cnitblog.com/Raistlin/archive/2005/07/13/922.html</link><dc:creator>Raistlin</dc:creator><author>Raistlin</author><pubDate>Wed, 13 Jul 2005 02:06:00 GMT</pubDate><guid>http://www.cnitblog.com/Raistlin/archive/2005/07/13/922.html</guid><wfw:comment>http://www.cnitblog.com/Raistlin/comments/922.html</wfw:comment><comments>http://www.cnitblog.com/Raistlin/archive/2005/07/13/922.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/Raistlin/comments/commentRss/922.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/Raistlin/services/trackbacks/922.html</trackback:ping><description><![CDATA[《上帝与新物理学》是一本谈论新物理学对以前属于宗教的问题产生的影响的书。在书的最后一章，谈到剑桥数学家约翰·康威发明的叫“生命”(life patterns)的游戏，场景是象围棋一样的格子，游戏规则是：<BR>1，有2个或者3个邻子的棋子在下一代(下一步)仍然存活 <BR>2，没有或只有1个邻近棋子要死(于孤单)，有4个或4个以上的邻子的棋子要死（于拥挤） <BR>3，若1个空格正好与3个不空的格为邻，那么，这个空格就要生出一个棋子来<BR>根据这些规则，某些起始的图形能够演化出“各种最令人惊讶的美丽图案”。书上有两个例子。<BR>我看到这里就想着写个程序来实现这样的“游戏”，并一边兴奋的想象着各种各样的图案，我将会是那些二维生物的上帝！<BR>刚好我在学WTL，昨天就用WTL写了个程序，一开始我对规则的理解并不正确，达不到书上程序的效果，程序改得很沮丧，哪天把程序写完整了再上传吧...<IMG height=19 src="http://www.cnitblog.com/Emoticons/confused_smile.gif" width=19 border=0><BR>今天早上用google找了一下'生命 约翰 康威'....原来人家已经..原来这个游戏从1970年就被人无数次的写过...甚至都可以找到applet源代码<BR><A href="http://www.ibiblio.org/lifepatterns/">http://www.ibiblio.org/lifepatterns/</A><BR><A href="http://www.radicaleye.com/lifepage/">http://www.radicaleye.com/lifepage/</A><BR><img src ="http://www.cnitblog.com/Raistlin/aggbug/922.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/Raistlin/" target="_blank">Raistlin</a> 2005-07-13 10:06 <a href="http://www.cnitblog.com/Raistlin/archive/2005/07/13/922.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>