Skip to content

Commit 13fcb60

Browse files
committed
Added a faster random number generator, many performance improvements.
1 parent 1f4f413 commit 13fcb60

11 files changed

+181
-95
lines changed

SalemOptimizer.sln

+3
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,7 @@ Global
1919
GlobalSection(SolutionProperties) = preSolution
2020
HideSolutionNode = FALSE
2121
EndGlobalSection
22+
GlobalSection(Performance) = preSolution
23+
HasPerformanceSessions = true
24+
EndGlobalSection
2225
EndGlobal

SalemOptimizer/EvaluationState.cs

+14-10
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,26 @@ public class EvaluationState
99
private int[] proficiencies = new int[15];
1010
private int[] inspirationalUses = new int[InspirationalDatabase.Inspirationals.Count];
1111

12-
void AddProficiency(int kind, int value, double weight)
13-
{
14-
proficiencies[kind] += value;
15-
16-
Inspiration += (int)(value * weight);
17-
}
18-
1912
public void AddInspirational(Inspirational inspirational)
2013
{
2114
var uses = inspirationalUses[inspirational.Id]++;
22-
var modifier = Math.Min(4d, 1d + uses * 0.5d);
15+
var modifier = Math.Min(8, 2 + uses);
16+
var givenProficiencies = inspirational.Proficiencies;
2317

24-
for (var i = 0; i < inspirational.Proficiencies.Length; i++)
18+
var inspiration = 0;
19+
20+
for (var i = 0; i < givenProficiencies.Length; i++)
2521
{
26-
AddProficiency(i, inspirational.Proficiencies[i], modifier);
22+
var val = givenProficiencies[i];
23+
24+
if (val != 0)
25+
{
26+
proficiencies[i] += val;
27+
inspiration += val * modifier;
28+
}
2729
}
30+
31+
Inspiration += inspiration / 2;
2832
}
2933

3034
public int GetValue(ProficiencyKind kind)

SalemOptimizer/Helper.cs

-53
This file was deleted.

SalemOptimizer/InspirationalBranch.cs

+14-14
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ public InspirationalBranch(Solver solver)
1414
{
1515
this.solver = solver;
1616

17-
Inspirational = solver.AvailableInspirationals[Helper.GetInt(solver.AvailableInspirationals.Length)];
17+
Inspirational = solver.AvailableInspirationals[solver.RandomHelper.GetShort(solver.AvailableInspirationals.Length)];
1818
}
1919

2020
public InspirationalBranch CreateRandomNode()
2121
{
2222
var newNode = new InspirationalBranch(solver);
23-
newNode.Inspirational = solver.AvailableInspirationals[Helper.GetInt(solver.AvailableInspirationals.Length)];
23+
newNode.Inspirational = solver.AvailableInspirationals[solver.RandomHelper.GetShort(solver.AvailableInspirationals.Length)];
2424

2525
return newNode;
2626
}
@@ -43,32 +43,32 @@ public IEnumerable<string> GetNames()
4343

4444
public void Mutate()
4545
{
46-
if (Helper.Mutate(100))
46+
if (solver.RandomHelper.Mutate(100))
4747
{
48-
Inspirational = solver.AvailableInspirationals[Helper.GetInt(solver.AvailableInspirationals.Length)];
48+
Inspirational = solver.AvailableInspirationals[solver.RandomHelper.GetShort(solver.AvailableInspirationals.Length)];
4949
}
5050

5151
if (LeftNode != null) LeftNode.Mutate();
5252
if (RightNode != null) RightNode.Mutate();
5353

5454
if (LeftNode == null)
5555
{
56-
if (Helper.Mutate(20)) LeftNode = CreateRandomNode();
57-
else if (Helper.Mutate(20)) LeftNode = this.Clone();
56+
if (solver.RandomHelper.Mutate(20)) LeftNode = CreateRandomNode();
57+
else if (solver.RandomHelper.Mutate(20)) LeftNode = this.Clone(solver);
5858
}
5959
else
6060
{
61-
if (Helper.Mutate(50)) LeftNode = null;
61+
if (solver.RandomHelper.Mutate(50)) LeftNode = null;
6262
}
6363

6464
if (RightNode == null)
6565
{
66-
if (Helper.Mutate(20)) RightNode = CreateRandomNode();
67-
else if (Helper.Mutate(20)) RightNode = this.Clone();
66+
if (solver.RandomHelper.Mutate(20)) RightNode = CreateRandomNode();
67+
else if (solver.RandomHelper.Mutate(20)) RightNode = this.Clone(solver);
6868
}
6969
else
7070
{
71-
if (Helper.Mutate(50)) RightNode = null;
71+
if (solver.RandomHelper.Mutate(50)) RightNode = null;
7272
}
7373
}
7474

@@ -83,13 +83,13 @@ public void Evaluate(EvaluationState engine)
8383
}
8484
}
8585

86-
public InspirationalBranch Clone()
86+
public InspirationalBranch Clone(Solver solver)
8787
{
8888
InspirationalBranch clone = new InspirationalBranch(solver);
8989
clone.Inspirational = Inspirational;
9090

91-
if (LeftNode != null) clone.LeftNode = LeftNode.Clone();
92-
if (RightNode != null) clone.RightNode = RightNode.Clone();
91+
if (LeftNode != null) clone.LeftNode = LeftNode.Clone(solver);
92+
if (RightNode != null) clone.RightNode = RightNode.Clone(solver);
9393

9494
return clone;
9595
}
@@ -102,7 +102,7 @@ public InspirationalBranch GetRandomNode()
102102
var nodes = new List<InspirationalBranch>();
103103
TraverseNode(this, nodes);
104104

105-
var index = Helper.GetInt(nodes.Count);
105+
var index = solver.RandomHelper.GetShort(nodes.Count);
106106
return nodes[index];
107107
}
108108

SalemOptimizer/Leaderboard.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public void AddOrganism(Organism organism)
2727
{
2828
var tmp =
2929
organisms
30-
.Union(new[] { organism.Clone() })
30+
.Union(new[] { organism.Clone(null) })
3131
.GroupBy(i => i == null ? null : i.ToString())
3232
.Select(i => i.First());
3333

SalemOptimizer/MainForm.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ private async Task FindSolution(bool useLastBest)
186186

187187
var bestOfAll = leaderboard.GetBest();
188188

189-
bestOrganisms = bestOfAll.Select(i => i.Clone()).ToArray();
189+
bestOrganisms = bestOfAll.Select(i => i.Clone(null)).ToArray();
190190

191191
lvSolutions.Items.Clear();
192192

SalemOptimizer/Organism.cs

+7-7
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,14 @@ public void Tick()
6767
{
6868
InspirationalBranch clone = null;
6969

70-
clone = (InspirationalBranch)root.Clone();
70+
clone = (InspirationalBranch)root.Clone(solver);
7171
clone.Mutate();
7272

7373
var stateNew = new EvaluationState();
7474

7575
var newResult = Evaluate(clone, stateNew, problem);
7676

77-
if (newResult.CostTotal < Solution.CostTotal || Helper.Mutate(10))
77+
if (newResult.CostTotal < Solution.CostTotal || solver.RandomHelper.Mutate(10))
7878
{
7979
root = clone;
8080
Solution = newResult;
@@ -84,10 +84,10 @@ public void Tick()
8484
}
8585
}
8686

87-
public Organism Clone()
87+
public Organism Clone(Solver solver)
8888
{
89-
Organism clone = new Organism(solver, problem);
90-
clone.root = this.root.Clone();
89+
Organism clone = new Organism(solver ?? this.solver, problem);
90+
clone.root = this.root.Clone(solver ?? this.solver);
9191
clone.Solution = this.Solution;
9292
clone.lastEvaluation = lastEvaluation;
9393
clone.cachedNames = cachedNames;
@@ -96,8 +96,8 @@ public Organism Clone()
9696

9797
public Organism MakeCrossOver(Organism father)
9898
{
99-
var child = this.Clone();
100-
var fatherDna = father.GetRandomNode().Clone();
99+
var child = this.Clone(solver);
100+
var fatherDna = father.GetRandomNode().Clone(solver);
101101
var motherDna = child.GetRandomNode();
102102
motherDna.LeftNode = fatherDna.LeftNode;
103103
motherDna.RightNode = fatherDna.RightNode;

SalemOptimizer/RandomHelper.cs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace SalemOptimizer
6+
{
7+
public class RandomHelper
8+
{
9+
private static Random basicRandom = new Random();
10+
private RndXorshift rnd;
11+
12+
public RandomHelper()
13+
{
14+
lock (basicRandom)
15+
{
16+
rnd = new RndXorshift(basicRandom);
17+
}
18+
}
19+
20+
public ushort GetShort(int chance)
21+
{
22+
return (ushort)(rnd.Next() % chance);
23+
//return (ushort)Math.Min(chance - 1, ((rnd.Next() * chance) / ushort.MaxValue));
24+
}
25+
26+
public bool Mutate(int chance)
27+
{
28+
return GetShort(chance) == 1;
29+
}
30+
}
31+
}

SalemOptimizer/SalemOptimizer.csproj

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<DefineConstants>TRACE</DefineConstants>
3131
<ErrorReport>prompt</ErrorReport>
3232
<WarningLevel>4</WarningLevel>
33+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
3334
</PropertyGroup>
3435
<PropertyGroup>
3536
<StartupObject />
@@ -72,7 +73,8 @@
7273
</Compile>
7374
<Compile Include="SolutionInformation.cs" />
7475
<Compile Include="Solver.cs" />
75-
<Compile Include="Helper.cs" />
76+
<Compile Include="RandomHelper.cs" />
77+
<Compile Include="Xorshift.cs" />
7678
<EmbeddedResource Include="MainForm.resx">
7779
<DependentUpon>MainForm.cs</DependentUpon>
7880
</EmbeddedResource>

SalemOptimizer/Solver.cs

+11-8
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ public class Solver
1313
private readonly Inspirational[] availableInspirationals;
1414
private readonly CancellationToken cancellationToken;
1515
private readonly Organism[] includedOrganisms;
16+
public readonly RandomHelper RandomHelper;
1617

1718
public Solver(Problem problem, Inspirational[] availableInspirationals, CancellationToken cancellationToken, Organism[] includedOrganisms)
1819
{
1920
this.problem = problem;
2021
this.availableInspirationals = availableInspirationals;
2122
this.cancellationToken = cancellationToken;
2223
this.includedOrganisms = includedOrganisms;
24+
this.RandomHelper = new RandomHelper();
2325
}
2426

2527
public Inspirational[] AvailableInspirationals { get { return availableInspirationals; } }
@@ -40,7 +42,7 @@ public Organism[] Solve(bool prune)
4042

4143
if (includedOrganisms != null)
4244
{
43-
foreach (var organism in includedOrganisms.Select(i => i.Clone()))
45+
foreach (var organism in includedOrganisms.Select(i => i.Clone(this)))
4446
{
4547
organisms.Add(organism);
4648
leaderboard.AddOrganism(organism);
@@ -83,24 +85,25 @@ public Organism[] Solve(bool prune)
8385
}
8486
}
8587

86-
if (Helper.GetInt(10) == 1)
88+
if (RandomHelper.GetShort(10) == 1)
8789
{
8890
organisms.Remove(worst);
89-
Organism clone = best.Clone();
91+
Organism clone = best.Clone(this);
9092
organisms.Add(clone);
9193
}
92-
else if (Helper.GetInt(30) == 1)
94+
else if (RandomHelper.GetShort(30) == 1)
9395
{
9496
organisms.Remove(worst);
95-
int index = Helper.GetInt(organisms.Count);
96-
Organism clone = organisms[index].Clone();
97+
98+
var index = RandomHelper.GetShort(organisms.Count);
99+
Organism clone = organisms[index].Clone(this);
97100
organisms.Add(clone);
98101
}
99-
else if (Helper.GetInt(100) == 1)
102+
else if (RandomHelper.GetShort(100) == 1)
100103
{
101104
organisms.Remove(worst);
102105

103-
int index = Helper.GetInt(organisms.Count);
106+
int index = RandomHelper.GetShort(organisms.Count);
104107
Organism mother = best;
105108
Organism father = organisms[index];
106109

0 commit comments

Comments
 (0)