@@ -11,72 +11,85 @@ The above copyright notice and this permission notice shall be included in all c
1111abstract class Model
1212{
1313 protected bool [ ] [ ] wave ;
14- protected double [ ] stationary ;
14+
15+ protected int [ ] [ ] [ ] propagator ;
16+ int [ ] [ ] [ ] compatible ;
1517 protected int [ ] observed ;
1618
17- protected bool [ ] changes ;
18- protected int [ ] stack ;
19- protected int stacksize ;
19+ Tuple < int , int > [ ] stack ;
20+ int stacksize ;
2021
2122 protected Random random ;
2223 protected int FMX , FMY , T ;
2324 protected bool periodic ;
2425
25- double [ ] logProb ;
26- double logT ;
26+ protected double [ ] weights ;
27+ double [ ] weightLogWeights ;
28+
29+ int [ ] sumsOfOnes ;
30+ double sumOfWeights , sumOfWeightLogWeights , startingEntropy ;
31+ double [ ] sumsOfWeights , sumsOfWeightLogWeights , entropies ;
2732
28- protected Model ( int width , int height )
33+ protected Model ( int width , int height )
2934 {
3035 FMX = width ;
3136 FMY = height ;
37+ }
3238
39+ void Init ( )
40+ {
3341 wave = new bool [ FMX * FMY ] [ ] ;
34- changes = new bool [ FMX * FMY ] ;
42+ compatible = new int [ wave . Length ] [ ] [ ] ;
43+ for ( int i = 0 ; i < wave . Length ; i ++ )
44+ {
45+ wave [ i ] = new bool [ T ] ;
46+ compatible [ i ] = new int [ T ] [ ] ;
47+ for ( int t = 0 ; t < T ; t ++ ) compatible [ i ] [ t ] = new int [ 4 ] ;
48+ }
49+
50+ weightLogWeights = new double [ T ] ;
51+ sumOfWeights = 0 ;
52+ sumOfWeightLogWeights = 0 ;
53+
54+ for ( int t = 0 ; t < T ; t ++ )
55+ {
56+ weightLogWeights [ t ] = weights [ t ] * Math . Log ( weights [ t ] ) ;
57+ sumOfWeights += weights [ t ] ;
58+ sumOfWeightLogWeights += weightLogWeights [ t ] ;
59+ }
60+
61+ startingEntropy = Math . Log ( sumOfWeights ) - sumOfWeightLogWeights / sumOfWeights ;
3562
36- stack = new int [ FMX * FMY ] ;
63+ sumsOfOnes = new int [ FMX * FMY ] ;
64+ sumsOfWeights = new double [ FMX * FMY ] ;
65+ sumsOfWeightLogWeights = new double [ FMX * FMY ] ;
66+ entropies = new double [ FMX * FMY ] ;
67+
68+ stack = new Tuple < int , int > [ wave . Length * T ] ;
3769 stacksize = 0 ;
3870 }
3971
40- protected abstract void Propagate ( ) ;
41-
4272 bool ? Observe ( )
4373 {
4474 double min = 1E+3 ;
4575 int argmin = - 1 ;
4676
4777 for ( int i = 0 ; i < wave . Length ; i ++ )
4878 {
49- if ( OnBoundary ( i ) ) continue ;
79+ if ( OnBoundary ( i % FMX , i / FMX ) ) continue ;
5080
51- bool [ ] w = wave [ i ] ;
52- int amount = 0 ;
53- double sum = 0 ;
81+ int amount = sumsOfOnes [ i ] ;
82+ if ( amount == 0 ) return false ;
5483
55- for ( int t = 0 ; t < T ; t ++ ) if ( w [ t ] )
84+ double entropy = entropies [ i ] ;
85+ if ( amount > 1 && entropy <= min )
86+ {
87+ double noise = 1E-6 * random . NextDouble ( ) ;
88+ if ( entropy + noise < min )
5689 {
57- amount += 1 ;
58- sum += stationary [ t ] ;
90+ min = entropy + noise ;
91+ argmin = i ;
5992 }
60-
61- if ( sum == 0 ) return false ;
62-
63- double noise = 1E-6 * random . NextDouble ( ) ;
64-
65- double entropy ;
66- if ( amount == 1 ) entropy = 0 ;
67- else if ( amount == T ) entropy = logT ;
68- else
69- {
70- double mainSum = 0 ;
71- double logSum = Math . Log ( sum ) ;
72- for ( int t = 0 ; t < T ; t ++ ) if ( w [ t ] ) mainSum += stationary [ t ] * logProb [ t ] ;
73- entropy = logSum - mainSum / sum ;
74- }
75-
76- if ( entropy > 0 && entropy + noise < min )
77- {
78- min = entropy + noise ;
79- argmin = i ;
8093 }
8194 }
8295
@@ -88,19 +101,56 @@ protected Model(int width, int height)
88101 }
89102
90103 double [ ] distribution = new double [ T ] ;
91- for ( int t = 0 ; t < T ; t ++ ) distribution [ t ] = wave [ argmin ] [ t ] ? stationary [ t ] : 0 ;
104+ for ( int t = 0 ; t < T ; t ++ ) distribution [ t ] = wave [ argmin ] [ t ] ? weights [ t ] : 0 ;
92105 int r = distribution . Random ( random . NextDouble ( ) ) ;
93- for ( int t = 0 ; t < T ; t ++ ) wave [ argmin ] [ t ] = t == r ;
94- Change ( argmin ) ;
106+
107+ bool [ ] w = wave [ argmin ] ;
108+ for ( int t = 0 ; t < T ; t ++ ) if ( w [ t ] != ( t == r ) ) Ban ( argmin , t ) ;
95109
96110 return null ;
97111 }
98112
113+ protected void Propagate ( )
114+ {
115+ while ( stacksize > 0 )
116+ {
117+ var e1 = stack [ stacksize - 1 ] ;
118+ stacksize -- ;
119+
120+ int i1 = e1 . Item1 ;
121+ int x1 = i1 % FMX , y1 = i1 / FMX ;
122+ bool [ ] w1 = wave [ i1 ] ;
123+
124+ for ( int d = 0 ; d < 4 ; d ++ )
125+ {
126+ int dx = DX [ d ] , dy = DY [ d ] ;
127+ int x2 = x1 + dx , y2 = y1 + dy ;
128+ if ( OnBoundary ( x2 , y2 ) ) continue ;
129+
130+ if ( x2 < 0 ) x2 += FMX ;
131+ else if ( x2 >= FMX ) x2 -= FMX ;
132+ if ( y2 < 0 ) y2 += FMY ;
133+ else if ( y2 >= FMY ) y2 -= FMY ;
134+
135+ int i2 = x2 + y2 * FMX ;
136+ int [ ] p = propagator [ d ] [ e1 . Item2 ] ;
137+ int [ ] [ ] compat = compatible [ i2 ] ;
138+
139+ for ( int l = 0 ; l < p . Length ; l ++ )
140+ {
141+ int t2 = p [ l ] ;
142+ int [ ] comp = compat [ t2 ] ;
143+
144+ comp [ d ] -- ;
145+ if ( comp [ d ] == 0 ) Ban ( i2 , t2 ) ;
146+ }
147+ }
148+ }
149+ }
150+
99151 public bool Run ( int seed , int limit )
100152 {
101- logT = Math . Log ( T ) ;
102- logProb = new double [ T ] ;
103- for ( int t = 0 ; t < T ; t ++ ) logProb [ t ] = Math . Log ( stationary [ t ] ) ;
153+ if ( wave == null ) Init ( ) ;
104154
105155 Clear ( ) ;
106156 random = new Random ( seed ) ;
@@ -115,24 +165,47 @@ public bool Run(int seed, int limit)
115165 return true ;
116166 }
117167
118- protected void Change ( int i )
168+ protected void Ban ( int i , int t )
119169 {
120- if ( changes [ i ] ) return ;
170+ wave [ i ] [ t ] = false ;
121171
122- stack [ stacksize ] = i ;
172+ int [ ] comp = compatible [ i ] [ t ] ;
173+ for ( int d = 0 ; d < 4 ; d ++ ) comp [ d ] = 0 ;
174+ stack [ stacksize ] = new Tuple < int , int > ( i , t ) ;
123175 stacksize ++ ;
124- changes [ i ] = true ;
176+
177+ double sum = sumsOfWeights [ i ] ;
178+ entropies [ i ] += sumsOfWeightLogWeights [ i ] / sum - Math . Log ( sum ) ;
179+
180+ sumsOfOnes [ i ] -= 1 ;
181+ sumsOfWeights [ i ] -= weights [ t ] ;
182+ sumsOfWeightLogWeights [ i ] -= weightLogWeights [ t ] ;
183+
184+ sum = sumsOfWeights [ i ] ;
185+ entropies [ i ] -= sumsOfWeightLogWeights [ i ] / sum - Math . Log ( sum ) ;
125186 }
126187
127188 protected virtual void Clear ( )
128189 {
129190 for ( int i = 0 ; i < wave . Length ; i ++ )
130191 {
131- for ( int t = 0 ; t < T ; t ++ ) wave [ i ] [ t ] = true ;
132- changes [ i ] = false ;
192+ for ( int t = 0 ; t < T ; t ++ )
193+ {
194+ wave [ i ] [ t ] = true ;
195+ for ( int d = 0 ; d < 4 ; d ++ ) compatible [ i ] [ t ] [ d ] = propagator [ opposite [ d ] ] [ t ] . Length ;
196+ }
197+
198+ sumsOfOnes [ i ] = weights . Length ;
199+ sumsOfWeights [ i ] = sumOfWeights ;
200+ sumsOfWeightLogWeights [ i ] = sumOfWeightLogWeights ;
201+ entropies [ i ] = startingEntropy ;
133202 }
134203 }
135204
136- protected abstract bool OnBoundary ( int i ) ;
205+ protected abstract bool OnBoundary ( int x , int y ) ;
137206 public abstract System . Drawing . Bitmap Graphics ( ) ;
207+
208+ protected static int [ ] DX = { - 1 , 0 , 1 , 0 } ;
209+ protected static int [ ] DY = { 0 , 1 , 0 , - 1 } ;
210+ static int [ ] opposite = { 2 , 3 , 0 , 1 } ;
138211}
0 commit comments