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 }