This repository has been archived by the owner on Jun 17, 2020. It is now read-only.
/
MetaFitness.cs
243 lines (214 loc) · 8.73 KB
/
MetaFitness.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/// ------------------------------------------------------
/// SwarmOps - Numeric and heuristic optimization for C#
/// Copyright (C) 2003-2011 Magnus Erik Hvass Pedersen.
/// Please see the file license.txt for license details.
/// SwarmOps on the internet: http://www.Hvass-Labs.org/
/// ------------------------------------------------------
using System.Diagnostics;
namespace SwarmOps.Optimizers
{
/// <summary>
/// Compute the standard Meta-Fitness measure, that is,
/// perform a number of optimization runs on different
/// problems and sum their results.
/// </summary>
/// <remarks>
/// Preemptive Fitness Evaluation is used in that optimizations
/// will be attempted aborted once the meta-fitness becomes
/// worse than the Preemptive Fitness Limit (aka. fitnessLimit).
/// In addition, the array of problems are being sorted at the
/// end of each meta-fitness computation, so as to allow the worst
/// performing problems to be optimized first in the next meta-fitness
/// computation, so as to decrease the computation time further still.
/// </remarks>
public class MetaFitness : Problem
{
#region Constructors.
/// <summary>
/// Construct the object, un-weighted problems.
/// </summary>
/// <param name="optimizer">Optimizer to be used.</param>
/// <param name="problems">Array of problems to be optimized.</param>
/// <param name="numRuns">Number of optimization runs per problem.</param>
/// <param name="maxIterations">Max number of optimization iterations.</param>
public MetaFitness(Optimizer optimizer, Problem[] problems, int numRuns, int maxIterations)
: base(maxIterations)
{
Optimizer = optimizer;
NumRuns = numRuns;
ProblemIndex = new ProblemIndex(problems);
}
/// <summary>
/// Construct the object, weighted problems.
/// </summary>
/// <param name="optimizer">Optimize to be used.</param>
/// <param name="weightedProblems">Array of weighted problems to be optimized.</param>
/// <param name="numRuns">Number of optimization runs per problem.</param>
/// <param name="maxIterations">Max number of optimization iterations.</param>
public MetaFitness(Optimizer optimizer, WeightedProblem[] weightedProblems, int numRuns, int maxIterations)
: base(maxIterations)
{
Optimizer = optimizer;
NumRuns = numRuns;
ProblemIndex = new ProblemIndex(weightedProblems);
}
#endregion
#region Public fields.
/// <summary>
/// Number of optimization runs to be performed for each problem.
/// </summary>
public int NumRuns
{
get;
private set;
}
/// <summary>
/// Optimizer to use in optimizations.
/// </summary>
public Optimizer Optimizer
{
get;
protected set;
}
#endregion
#region Base-class overrides.
/// <summary>
/// Name of the optimization problem.
/// </summary>
public override string Name
{
get { return "MetaFitness (" + Optimizer.Name + ")"; }
}
/// <summary>
/// Return LowerBound for Optimizer.
/// </summary>
public override double[] LowerBound
{
get { return Optimizer.LowerBound; }
}
/// <summary>
/// Return UpperBound for Optimizer.
/// </summary>
public override double[] UpperBound
{
get { return Optimizer.UpperBound; }
}
/// <summary>
/// Return LowerInit for Optimizer.
/// </summary>
public override double[] LowerInit
{
get { return Optimizer.LowerInit; }
}
/// <summary>
/// Return UpperInit for Optimizer.
/// </summary>
public override double[] UpperInit
{
get { return Optimizer.UpperInit; }
}
/// <summary>
/// Return Dimensionality for Optimizer.
/// </summary>
public override int Dimensionality
{
get { return Optimizer.Dimensionality; }
}
/// <summary>
/// Return Zero which is the minimum fitness possible for a
/// meta-fitness measure.
/// </summary>
public override double MinFitness
{
get { return 0; }
}
/// <summary>
/// Return ParameterName for Optimizer.
/// </summary>
public override string[] ParameterName
{
get { return Optimizer.ParameterName; }
}
/// <summary>
/// Compute the meta-fitness measure by passing the
/// given parameters to the Optimizer, and perform
/// optimization runs on the array of problems
/// until the fitness compute exceeds the fitnessLimit.
/// </summary>
/// <param name="parameters">Parameters to use for the Optimizer.</param>
/// <param name="fitnessLimit">Preemptive Fitness Limit</param>
/// <returns>Fitness value.</returns>
public override double Fitness(double[] parameters, double fitnessLimit)
{
// Initialize the fitness-sum.
double fitnessSum = 0;
// Iterate over the problems.
for (int i = 0; i < ProblemIndex.Count && fitnessSum<fitnessLimit; i++)
{
// Assign the problem to the optimizer.
Optimizer.Problem = ProblemIndex.GetProblem(i);
// Get the weight associated with this problem.
double weight = ProblemIndex.GetWeight(i);
// Use another fitness summation because we need to keep
// track of the performance on each problem.
double fitnessSumInner = 0;
// Perform a number of optimization runs.
for (int j = 0; j < NumRuns && fitnessSum < fitnessLimit; j++)
{
// Perform one optimization run on the problem.
Result result = Optimizer.Optimize(parameters, fitnessLimit - fitnessSum);
// Get the best fitness result from optimization and adjust it
// by subtracting its minimum possible value.
double fitness = result.Fitness;
double fitnessAdjusted = fitness - Optimizer.MinFitness;
// Ensure adjusted fitness is non-negative, otherwise Preemptive
// Fitness Evaluation does not work.
Debug.Assert(fitnessAdjusted >= 0);
// Apply weight to the adjusted fitness.
fitnessAdjusted *= weight;
// Accumulate both fitness sums.
fitnessSumInner += fitnessAdjusted;
fitnessSum += fitnessAdjusted;
}
// Set the fitness result achieved on the problem.
// This was why we needed an extra summation variable.
ProblemIndex.SetFitness(i, fitnessSumInner);
}
// Sort the optimization problems so that the worst
// performing will be attempted optimized first, when
// this method is called again.
ProblemIndex.Sort();
return fitnessSum;
}
/// <summary>
/// Enforce constraints and evaluate feasiblity.
/// </summary>
/// <param name="parameters">Parameters to use for the Optimizer.</param>
public override bool EnforceConstraints(ref double[] parameters)
{
return Optimizer.EnforceConstraints(ref parameters);
}
/// <summary>
/// Evaluate feasibility (constraint satisfaction).
/// </summary>
/// <param name="parameters">Parameters to use for the Optimizer.</param>
public override bool Feasible(double[] parameters)
{
return Optimizer.Feasible(parameters);
}
/// <summary>
/// At beginning of new meta-optimization run print a newline.
/// </summary>
public override void BeginOptimizationRun()
{
Tools.PrintNewline();
}
#endregion
#region Protected members.
/// <summary>
/// Sorted index of optimization problems.
/// </summary>
protected ProblemIndex ProblemIndex;
#endregion
}
}