Skip to content

Commit 97ffd8d

Browse files
committed
Added an option to prune the organisms in the leaderboard, removing those that are obviously not optimal (we have all the inspirationals of that organism plus some extra, while having worse score).
1 parent 7435d79 commit 97ffd8d

File tree

7 files changed

+98
-46
lines changed

7 files changed

+98
-46
lines changed

SalemOptimizer/EvaluationState.cs

+13
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,18 @@ public int GetValue(ProficiencyKind kind)
3232
}
3333

3434
public int Inspiration { get; set; }
35+
36+
public bool IsSupersetOf(EvaluationState state)
37+
{
38+
bool anyBigger = false;
39+
40+
for (var i = 0; i < inspirationalUses.Length; i++)
41+
{
42+
if (inspirationalUses[i] < state.inspirationalUses[i]) return false;
43+
if (inspirationalUses[i] > state.inspirationalUses[i]) anyBigger = true;
44+
}
45+
46+
return anyBigger;
47+
}
3548
}
3649
}

SalemOptimizer/Leaderboard.cs

+18-7
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,37 @@ namespace SalemOptimizer
88
{
99
public class Leaderboard
1010
{
11-
private int slots = 5;
11+
private readonly int slots;
12+
private readonly bool prune;
1213
private Organism[] organisms;
1314

1415
private double worst = double.MaxValue;
1516

16-
public Leaderboard(int slots)
17+
public Leaderboard(int slots, bool prune)
1718
{
1819
this.slots = slots;
19-
this.organisms = new Organism[slots];
20+
this.prune = prune;
21+
this.organisms = new Organism[0];
2022
}
2123

2224
public void AddOrganism(Organism organism)
2325
{
24-
if (organism.Solution.CostTotal < worst)
26+
if (organism.Solution.CostTotal < worst || organisms.Length < slots)
2527
{
26-
organisms =
28+
var tmp =
2729
organisms
28-
.Union(new [] { organism.Clone() })
30+
.Union(new[] { organism.Clone() })
2931
.GroupBy(i => i == null ? null : i.ToString())
30-
.Select(i => i.First())
32+
.Select(i => i.First());
33+
34+
if (prune)
35+
{
36+
var tmp2 = tmp.ToArray();
37+
tmp = tmp.Where(j => !tmp2.Any(i => i.Solution.CostTotal < j.Solution.CostTotal && j.IsSupersetOf(i)));
38+
}
39+
40+
organisms =
41+
tmp
3142
.OrderBy(i => i == null ? double.MaxValue : i.Solution.CostTotal)
3243
.Take(slots)
3344
.ToArray();

SalemOptimizer/MainForm.Designer.cs

+24-10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

SalemOptimizer/MainForm.cs

+11-13
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ private async Task FindSolution(bool useLastBest)
150150

151151
UseWaitCursor = true;
152152

153+
var prune = cbxPrune.Checked;
154+
153155
var problem =
154156
new Problem()
155157
.Add(ProficiencyKind.ArtsAndCrafts, nudArtsAndCrafts.Value)
@@ -172,29 +174,25 @@ private async Task FindSolution(bool useLastBest)
172174

173175
cancellationTokenSource = new CancellationTokenSource();
174176

175-
var solvers = Enumerable.Range(1, 4).Select(i => Task.Run(() => new Solver(problem, availableInspirationals, cancellationTokenSource.Token, useLastBest ? bestOrganisms : null).Solve())).ToArray();
177+
var solvers = Enumerable.Range(1, 4).Select(i => Task.Run(() => new Solver(problem, availableInspirationals, cancellationTokenSource.Token, useLastBest ? bestOrganisms : null).Solve(prune))).ToArray();
176178

177179
var best = await Task.WhenAll(solvers);
178180

179181
// Aggregate the best results and fill them into the results control
180-
var bestOfAll =
181-
best
182-
.SelectMany(i => i)
183-
.Select(i => new { Name = i.ToString(), Organism = i, Solution = i.Solution })
184-
.GroupBy(i => i.Name)
185-
.Select(i => i.First())
186-
.OrderBy(i => i.Solution.CostTotal)
187-
.Take(5)
188-
.ToArray();
189-
190-
bestOrganisms = bestOfAll.Select(i => i.Organism.Clone()).ToArray();
182+
var leaderboard = new Leaderboard(5, prune);
183+
184+
foreach (var organism in best.SelectMany(i => i)) leaderboard.AddOrganism(organism);
185+
186+
var bestOfAll = leaderboard.GetBest();
187+
188+
bestOrganisms = bestOfAll.Select(i => i.Clone()).ToArray();
191189

192190
lvSolutions.Items.Clear();
193191

194192
foreach (var organism in bestOfAll)
195193
{
196194
var lvi = new ListViewItem();
197-
lvi.Text = organism.Name;
195+
lvi.Text = organism.ToString();
198196
lvi.ForeColor = organism.Solution.IncompletenessPenalty == 0 ? Color.Green : Color.Red;
199197
lvi.SubItems.Add(organism.Solution.CostTotal.ToString("###,###,###"));
200198
lvSolutions.Items.Add(lvi);

SalemOptimizer/Organism.cs

+27-11
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,43 @@ public class Organism
1111
private Problem problem;
1212

1313
public SolutionInformation Solution = new SolutionInformation { CostTotal = int.MaxValue };
14+
private EvaluationState lastEvaluation;
1415

1516
public Organism(Solver solver, Problem problem)
1617
{
1718
this.solver = solver;
1819
this.problem = problem;
1920

2021
root = new InspirationalBranch(solver) { LeftNode = new InspirationalBranch(solver), RightNode = new InspirationalBranch(solver) };
21-
Solution = Evaluate(root, problem);
22+
lastEvaluation = new EvaluationState();
23+
Solution = Evaluate(root, lastEvaluation, problem);
2224
}
2325

26+
public bool IsSupersetOf(Organism organism)
27+
{
28+
if (lastEvaluation == null || organism.lastEvaluation == null) return false;
29+
30+
return lastEvaluation.IsSupersetOf(organism.lastEvaluation);
31+
}
32+
2433
public override string ToString()
2534
{
2635
return root.GetNames();
2736
}
2837

29-
public static SolutionInformation Evaluate(InspirationalBranch root, Problem problem)
38+
private static SolutionInformation Evaluate(InspirationalBranch root, EvaluationState state, Problem problem)
3039
{
31-
EvaluationState engine = new EvaluationState();
32-
root.Evaluate(engine);
40+
root.Evaluate(state);
3341

3442
var cost = new SolutionInformation();
3543

3644
// Add the total inspiration cost
37-
cost.InspirationTotal += engine.Inspiration;
45+
cost.InspirationTotal += state.Inspiration;
3846

3947
// Add extra cost for incomplete solutions
4048
foreach (var needed in problem.Proficiencies)
4149
{
42-
cost.IncompletenessPenalty += Math.Max(0d, needed.Value - engine.GetValue(needed.Key)) * 1000;
50+
cost.IncompletenessPenalty += Math.Max(0d, needed.Value - state.GetValue(needed.Key)) * 1000;
4351
}
4452

4553
cost.CostTotal = cost.InspirationTotal + cost.IncompletenessPenalty;
@@ -54,16 +62,21 @@ public void Tick()
5462
clone = (InspirationalBranch)root.Clone();
5563
clone.Mutate();
5664

57-
var engineNew = new EvaluationState();
58-
var engineOld = new EvaluationState();
65+
var stateNew = new EvaluationState();
66+
var stateOld = new EvaluationState();
5967

60-
var newResult = Evaluate(clone, problem);
61-
var oldResult = Evaluate(root, problem);
68+
var newResult = Evaluate(clone, stateNew, problem);
69+
var oldResult = Evaluate(root, stateOld, problem);
6270

6371
if (newResult.CostTotal < oldResult.CostTotal || Helper.Mutate(10))
6472
{
6573
root = clone;
6674
Solution = newResult;
75+
lastEvaluation = stateNew;
76+
}
77+
else
78+
{
79+
lastEvaluation = stateOld;
6780
}
6881
}
6982

@@ -72,6 +85,7 @@ public Organism Clone()
7285
Organism clone = new Organism(solver, problem);
7386
clone.root = this.root.Clone();
7487
clone.Solution = this.Solution;
88+
clone.lastEvaluation = lastEvaluation;
7589
return clone;
7690
}
7791

@@ -83,7 +97,9 @@ public Organism MakeCrossOver(Organism father)
8397
motherDna.LeftNode = fatherDna.LeftNode;
8498
motherDna.RightNode = fatherDna.RightNode;
8599

86-
child.Solution = Evaluate(child.root, problem);
100+
var state = new EvaluationState();
101+
child.Solution = Evaluate(child.root, state, problem);
102+
child.lastEvaluation = state;
87103
return child;
88104
}
89105

SalemOptimizer/Properties/AssemblyInfo.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@
3232
// You can specify all the values or you can default the Build and Revision Numbers
3333
// by using the '*' as shown below:
3434
// [assembly: AssemblyVersion("1.0.*")]
35-
[assembly: AssemblyVersion("1.4.0.0")]
36-
[assembly: AssemblyFileVersion("1.4.0.0")]
37-
[assembly: AssemblyInformationalVersion("26. 1. 2015")]
35+
[assembly: AssemblyVersion("1.5.0.0")]
36+
[assembly: AssemblyFileVersion("1.5.0.0")]
37+
[assembly: AssemblyInformationalVersion("29. 1. 2015")]

SalemOptimizer/Solver.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ public Solver(Problem problem, Inspirational[] availableInspirationals, Cancella
2424

2525
public Inspirational[] AvailableInspirationals { get { return availableInspirationals; } }
2626

27-
public Organism[] Solve()
27+
public Organism[] Solve(bool prune)
2828
{
29-
var leaderboard = new Leaderboard(5);
29+
var leaderboard = new Leaderboard(5, prune);
3030

3131
var organisms = new List<Organism>();
3232
var generations = 0;

0 commit comments

Comments
 (0)