Skip to content

Commit fad1066

Browse files
committed
optimizations of Fehr and Courant, x20 speed-up for the overlapping model
1 parent 3c8336d commit fad1066

File tree

4 files changed

+150
-205
lines changed

4 files changed

+150
-205
lines changed

Main.cs

+5
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ The above copyright notice and this permission notice shall be included in all c
88

99
using System;
1010
using System.Xml.Linq;
11+
using System.Diagnostics;
1112

1213
static class Program
1314
{
1415
static void Main()
1516
{
17+
Stopwatch sw = Stopwatch.StartNew();
18+
1619
Random random = new Random();
1720
XDocument xdoc = XDocument.Load("samples.xml");
1821

@@ -52,5 +55,7 @@ static void Main()
5255

5356
counter++;
5457
}
58+
59+
Console.WriteLine($"time = {sw.ElapsedMilliseconds}");
5560
}
5661
}

Model.cs

+124-51
Original file line numberDiff line numberDiff line change
@@ -11,72 +11,85 @@ The above copyright notice and this permission notice shall be included in all c
1111
abstract 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

Comments
 (0)