@@ -11,72 +11,85 @@ The above copyright notice and this permission notice shall be included in all c
11
11
abstract class Model
12
12
{
13
13
protected bool [ ] [ ] wave ;
14
- protected double [ ] stationary ;
14
+
15
+ protected int [ ] [ ] [ ] propagator ;
16
+ int [ ] [ ] [ ] compatible ;
15
17
protected int [ ] observed ;
16
18
17
- protected bool [ ] changes ;
18
- protected int [ ] stack ;
19
- protected int stacksize ;
19
+ Tuple < int , int > [ ] stack ;
20
+ int stacksize ;
20
21
21
22
protected Random random ;
22
23
protected int FMX , FMY , T ;
23
24
protected bool periodic ;
24
25
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 ;
27
32
28
- protected Model ( int width , int height )
33
+ protected Model ( int width , int height )
29
34
{
30
35
FMX = width ;
31
36
FMY = height ;
37
+ }
32
38
39
+ void Init ( )
40
+ {
33
41
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 ;
35
62
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 ] ;
37
69
stacksize = 0 ;
38
70
}
39
71
40
- protected abstract void Propagate ( ) ;
41
-
42
72
bool ? Observe ( )
43
73
{
44
74
double min = 1E+3 ;
45
75
int argmin = - 1 ;
46
76
47
77
for ( int i = 0 ; i < wave . Length ; i ++ )
48
78
{
49
- if ( OnBoundary ( i ) ) continue ;
79
+ if ( OnBoundary ( i % FMX , i / FMX ) ) continue ;
50
80
51
- bool [ ] w = wave [ i ] ;
52
- int amount = 0 ;
53
- double sum = 0 ;
81
+ int amount = sumsOfOnes [ i ] ;
82
+ if ( amount == 0 ) return false ;
54
83
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 )
56
89
{
57
- amount += 1 ;
58
- sum += stationary [ t ] ;
90
+ min = entropy + noise ;
91
+ argmin = i ;
59
92
}
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 ;
80
93
}
81
94
}
82
95
@@ -88,19 +101,56 @@ protected Model(int width, int height)
88
101
}
89
102
90
103
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 ;
92
105
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 ) ;
95
109
96
110
return null ;
97
111
}
98
112
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
+
99
151
public bool Run ( int seed , int limit )
100
152
{
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 ( ) ;
104
154
105
155
Clear ( ) ;
106
156
random = new Random ( seed ) ;
@@ -115,24 +165,47 @@ public bool Run(int seed, int limit)
115
165
return true ;
116
166
}
117
167
118
- protected void Change ( int i )
168
+ protected void Ban ( int i , int t )
119
169
{
120
- if ( changes [ i ] ) return ;
170
+ wave [ i ] [ t ] = false ;
121
171
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 ) ;
123
175
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 ) ;
125
186
}
126
187
127
188
protected virtual void Clear ( )
128
189
{
129
190
for ( int i = 0 ; i < wave . Length ; i ++ )
130
191
{
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 ;
133
202
}
134
203
}
135
204
136
- protected abstract bool OnBoundary ( int i ) ;
205
+ protected abstract bool OnBoundary ( int x , int y ) ;
137
206
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 } ;
138
211
}
0 commit comments