001 import swarm.space.*; 002 import swarm.defobj.*; 003 import swarm.*; 004 import java.util.*; 005 006 public class PatternSpace extends Discrete2dImpl{ 007 int width,height; 008 009 LinkedList remainingPoints; 010 LinkedList largestCluster; 011 LinkedList clusterData; 012 LinkedList clusterSizeData; 013 boolean checked[][]; 014 015 public PatternSpace(Zone aZone,int W,int H){ 016 super(aZone,W,H); 017 width=W; 018 height=H; 019 initializeSpace(); 020 } 021 022 /** 023 * コンストラクタの補助メソッド 024 */ 025 void initializeSpace(){ 026 remainingPoints=new LinkedList(); 027 checked=new boolean[height][width]; 028 clusterSizeData=new LinkedList(); 029 for(int i=0;i<height;++i){ 030 for(int j=0;j<width;++j){ 031 int[] pair={i,j}; 032 remainingPoints.add(pair); 033 this.putValue$atX$Y(0,i,j); 034 } 035 } 036 } 037 038 /** 039 * まだ点の置かれていない格子があるか 040 */ 041 public boolean remainingQ(){ 042 return !remainingPoints.isEmpty(); 043 } 044 045 /** 046 * PatternSpaceに新しい点をランダムに追加する。<BR> 047 * ここではクラスタリングの計算は行わない。 048 * この計算は重いと予想されるため、getPercolationProbが呼ばれたときのみ行う。 049 */ 050 public void update(){ 051 int pIndex=Globals.env.uniformIntRand.getIntegerWithMin$withMax(0,remainingPoints.size()-1); 052 int[] p=(int[])remainingPoints.get(pIndex); 053 remainingPoints.remove(pIndex); 054 int i=p[0]; 055 int j=p[1]; 056 this.putValue$atX$Y(1,i,j); 057 } 058 059 /** 060 * クラスタに分ける処理を行うメソッド<BR> 061 * ・はじめ、すべての点はunchecked<BR> 062 * ・点を順番に調べていく<BR> 063 * ・uncheckedの点につながっている点を再帰的に調べる(traceCluster)<BR> 064 * ・できあがったclusterDataの中で、最大のものが最大クラスタ<BR> 065 * <BR> 066 * これは再帰的な処理だが、もちろん反復でもできる。<BR> 067 * 参考:小田垣孝「パーコレーションの科学」第3章 068 */ 069 public void trace(){ 070 int clusterIndex=-1; 071 clusterData=new LinkedList(); 072 073 for(int i=0;i<height;++i){ 074 for(int j=0;j<width;++j){ 075 checked[i][j]=false; 076 } 077 } 078 079 for(int i=0;i<height;++i){ 080 for(int j=0;j<width;++j){ 081 if(!checked[i][j]){ 082 if(getValueAtX$Y(i,j)!=0){ 083 clusterIndex++; 084 clusterData.add(new LinkedList()); 085 traceCluster(i,j,clusterIndex); 086 } 087 } 088 } 089 } 090 091 int s,maxSize=0; 092 clusterSizeData.clear(); 093 Iterator it=clusterData.iterator(); 094 while(it.hasNext()){ 095 LinkedList cluster=(LinkedList)it.next(); 096 s=cluster.size(); 097 clusterSizeData.add(new Integer(s)); 098 if(maxSize<s){ 099 maxSize=s; 100 largestCluster=cluster; 101 } 102 } 103 104 for(int i=0;i<height;++i){ 105 for(int j=0;j<width;++j){ 106 if(this.getValueAtX$Y(i,j)==2){ 107 this.putValue$atX$Y(1,i,j); 108 } 109 } 110 } 111 112 it=largestCluster.iterator(); 113 int[] tmp; 114 while(it.hasNext()){ 115 tmp=(int[])it.next(); 116 int i=tmp[0]; 117 int j=tmp[1]; 118 putValue$atX$Y(2,i,j); 119 } 120 } 121 122 /** 123 * traceの補助メソッド 124 */ 125 void traceCluster(int i,int j,int ci){ 126 if(!checked[i][j]){ 127 checked[i][j]=true; 128 if(getValueAtX$Y(i,j)!=0){ 129 int[] pair={i,j}; 130 ((LinkedList)clusterData.get(ci)).add(pair); 131 if(i!=0) traceCluster(i-1,j,ci); 132 if(i!=height-1) traceCluster(i+1,j,ci); 133 if(j!=0) traceCluster(i,j-1,ci); 134 if(j!=width-1) traceCluster(i,j+1,ci); 135 } 136 } 137 } 138 139 /** 140 * 浸透確率を計算する。<BR> 141 * 内部で、PatternSpaceに最大クラスタサイズを問い合わせ、 142 * その結果と、全格子数の比が浸透確率である。 143 */ 144 public double getPercolationProb(){ 145 trace(); 146 return (double)largestCluster.size()/(width*height); 147 } 148 149 public LinkedList getClusterSizeData(){ 150 return clusterSizeData; 151 } 152 153 public int getClusterNum(){ 154 return clusterData.size(); 155 } 156 }