-
Notifications
You must be signed in to change notification settings - Fork 0
/
CrossEntropyMethod.cs
155 lines (140 loc) · 5.94 KB
/
CrossEntropyMethod.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AdversarialImage
{
class CrossEntropyMethod
{
Random r = new Random();
double objective_function(double[] vector)
{
double sum = 0f;
foreach (var f in vector)
{
sum += (double)Math.Pow(f, 2);
}
return -sum;
}
double QuadraticEquation(double[] vector)
{
// 5X^2 + 10X - 2 = 0 -> X=-2.183216 || X=0.183216
double sum = 5 * Math.Pow(vector[0], 2) + 10 * vector[0] - 2;
return -Math.Abs(sum);
}
double QuadraticEquation2(double[] vector)
{
// 5X^2 + 10X - 2 = 0 -> X=-2.183216 || X=0.183216
double sum1 = vector[0] * Math.Pow(0.183216, 2) + vector[1] * 0.183216 + vector[2];
double sum2 = vector[0] * Math.Pow(-2.183216, 2) + vector[1] * -2.183216 + vector[2];
return -(Math.Abs(sum1) + Math.Abs(sum2));
}
double random_variable(double min, double max)
{
return min + ((max - min) * r.NextDouble());
}
double random_gaussian(double mean = 0.0, double stdev = 1.0)
{
double u1, u2, w;
u1 = u2 = w = 0;
do
{
u1 = 2 * r.NextDouble() - 1;
u2 = 2 * r.NextDouble() - 1;
w = u1 * u1 + u2 * u2;
} while (w >= 1);
w = Math.Sqrt((-2.0 * Math.Log(w)) / w);
return mean + (u2 * w) * stdev;
}
double[] generate_sample(double[][] search_space, double[] means, double[] stdevs)
{
double[] vector = new double[search_space.Length];
for (int i = 0; i < vector.Length; i++)
{
vector[i] = random_gaussian(means[i], stdevs[i]);
vector[i] = Math.Max(vector[i], search_space[i][0]);
vector[i] = Math.Min(vector[i], search_space[i][1]);
}
return vector;
}
void update_distribution(double[][] samples, double alpha, ref double[] means, ref double[] stdevs)
{
for (int i = 0; i < means.Length; i++)
{
double[] tArray = new double[samples.Length];
for (int z = 0; z < samples.Length; z++)
{
tArray[z] = samples[z][i];
}
means[i] = alpha * means[i] + ((1.0 - alpha) * tArray.Average());
stdevs[i] = alpha * stdevs[i] + ((1.0 - alpha) * StandardDeviation(tArray.ToList()));
}
}
private double StandardDeviation(List<double> values)
{
double mean = values.Average();// (start, end);
double variance = Variance(values, mean, 0, values.Count);
return Math.Sqrt(variance);
}
private double Variance(List<double> values, double mean, int start, int end)
{
double variance = 0;
for (int i = start; i < end; i++)
{
variance += Math.Pow((values[i] - mean), 2);
}
int n = end - start;
if (start > 0) n -= 1;
return variance / (n);
}
double[] search(double[][] bounds, int max_iter, int num_samples, int num_update, double learning_rate)
{
double[] means = new double[bounds.Length];
double[] stdevs = new double[bounds.Length];
for (int i = 0; i < means.Count(); i++)
{
means[i] = random_variable(bounds[i][0], bounds[i][1]);
stdevs[i] = bounds[i][1] - bounds[i][0];
}
double[] best = null;
double bestScore = double.MinValue;
for (int t = 0; t < max_iter; t++)
{
double[][] samples = new double[num_samples][];
double[] scores = new double[num_samples];
for (int s = 0; s < num_samples; s++)
{
samples[s] = generate_sample(bounds, means, stdevs);
scores[s] = QuadraticEquation(samples[s]);
}
Array.Sort(scores, samples);
Array.Reverse(scores);
Array.Reverse(samples);
if (best == null || scores.First() > bestScore)
{
bestScore = scores.First();
best = samples.First();
}
double[][] selected = new double[num_update][];
Array.Copy(samples, selected, num_update);
update_distribution(selected, learning_rate, ref means, ref stdevs);
Console.WriteLine("iteration={0}, fitness={1}", t, bestScore);
}
return best;
}
public void Run()
{
double[][] parameters = new double[][] { new double[] { -500, 500 } }; //QuadraticEquation parameters
//double[][] parameters = new double[][] { new double[] { 4, 6 }, new double[] { 9, 11 }, new double[] { -3, -1} }; //QuadraticEquation2 parameters
//double[][] parameters = new double[][] { new double[] { -5, 5 }, new double[] { -5, 5 }, new double[] { -5, 5 } }; //object_function parameters
int maxIter = 100;
int nSamples = 50;
int nUpdate = 5;
double alpha = 1;
double[] best = search(parameters, maxIter, nSamples, nUpdate, alpha);
string str = string.Join(" | ", best.Select(a => a.ToString("N10")).ToArray());
Console.WriteLine("Best: " + str);
}
}
}