Skip to content

Commit 73ce370

Browse files
committed
Add Minimum Linear Arrangement portion.
Fix existing topological sort. Update to .NET core 3.1
1 parent 6e53912 commit 73ce370

22 files changed

+1697
-336
lines changed

AllProjects.sln

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Portent.Test", "Portent.Tes
2828
EndProject
2929
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Portent.Benchmark", "Portent.Benchmark\Portent.Benchmark.csproj", "{BD1A249D-0576-49EE-BC96-63B9545674BE}"
3030
EndProject
31+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinLA", "MinLA\MinLA.csproj", "{382F1CE8-1B54-4CFC-801A-05883A89295C}"
32+
EndProject
3133
Global
3234
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3335
Debug|Any CPU = Debug|Any CPU
@@ -46,6 +48,10 @@ Global
4648
{BD1A249D-0576-49EE-BC96-63B9545674BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
4749
{BD1A249D-0576-49EE-BC96-63B9545674BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
4850
{BD1A249D-0576-49EE-BC96-63B9545674BE}.Release|Any CPU.Build.0 = Release|Any CPU
51+
{382F1CE8-1B54-4CFC-801A-05883A89295C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
52+
{382F1CE8-1B54-4CFC-801A-05883A89295C}.Debug|Any CPU.Build.0 = Debug|Any CPU
53+
{382F1CE8-1B54-4CFC-801A-05883A89295C}.Release|Any CPU.ActiveCfg = Release|Any CPU
54+
{382F1CE8-1B54-4CFC-801A-05883A89295C}.Release|Any CPU.Build.0 = Release|Any CPU
4955
EndGlobalSection
5056
GlobalSection(SolutionProperties) = preSolution
5157
HideSolutionNode = FALSE

MinLA/Annealer.cs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System;
2+
3+
namespace MinLA
4+
{
5+
public static class Annealer
6+
{
7+
public static (double newCost, TR Arrangement) Anneal<T, TR>(T annealingProblem, int seed, double temperature = 400.0d, double coolingRate = 0.999d, double lowestTemperature = 0.001d)
8+
where T : IAnnealingProblem<TR>
9+
{
10+
var random = new Random(seed);
11+
var count = 0;
12+
var kept = 0;
13+
var rejected = 0;
14+
var uphill = 0;
15+
while (temperature > lowestTemperature)
16+
{
17+
var delta = annealingProblem.MakeRandomMove();
18+
if (delta <= 0)
19+
{
20+
kept++;
21+
annealingProblem.KeepLastMove();
22+
}
23+
else if (random.NextDouble() < temperature)
24+
{
25+
uphill++;
26+
annealingProblem.KeepLastMove();
27+
}
28+
else
29+
{
30+
rejected++;
31+
}
32+
33+
if (count++ == 100000)
34+
{
35+
count = 0;
36+
Console.WriteLine(annealingProblem.Cost + ", " + kept.ToString("D5") + ", " + rejected.ToString("D5") + ", " + uphill.ToString("D5"));
37+
kept = 0;
38+
rejected = 0;
39+
uphill = 0;
40+
}
41+
42+
temperature *= coolingRate;
43+
}
44+
45+
return (annealingProblem.Cost, annealingProblem.Result);
46+
}
47+
}
48+
}

MinLA/CacheAwareInstance.cs

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Portent;
4+
5+
namespace MinLA
6+
{
7+
public class CacheAwareInstance : IAnnealingProblem<int[]>
8+
{
9+
public int[] Result => _arrangementToDawgPointer;
10+
11+
public double Cost { get; private set; }
12+
13+
private readonly Random _rand = new Random(7654321);
14+
15+
public const int CacheSize = 16;
16+
17+
private bool BeforeChildren(int node, int newPosition)
18+
{
19+
var realFirstNode = _arrangementToDawgPointer[node];
20+
foreach (var neighbor in _convertedGraph[realFirstNode].Children)
21+
{
22+
var neighborPosition = _dawgToArrangementPointer[neighbor];
23+
if (neighborPosition <= newPosition)
24+
{
25+
return false;
26+
}
27+
}
28+
29+
return true;
30+
}
31+
public double MakeRandomMove()
32+
{
33+
//set _swapIndex1 and _swapIndex2
34+
//calculate and assign Delta
35+
var count = 0;
36+
int realNode1;
37+
int realNode2;
38+
while (true)
39+
{
40+
count++;
41+
if (count == 500)
42+
{
43+
Console.WriteLine("Could not find a valid swap");
44+
return double.MaxValue;
45+
}
46+
47+
var t1 = _rand.Next(0, _arrangementToDawgPointer.Length);
48+
var t2 = _rand.Next(0, _arrangementToDawgPointer.Length);
49+
if (t1 == t2)
50+
{
51+
continue;
52+
}
53+
54+
_swapIndex1 = Math.Min(t1, t2);
55+
_swapIndex2 = Math.Max(t1, t2);
56+
realNode1 = _arrangementToDawgPointer[_swapIndex1];
57+
realNode2 = _arrangementToDawgPointer[_swapIndex2];
58+
if ((_swapIndex2 == 0 && _convertedGraph[realNode1].Terminal) || (_swapIndex1 == 0 && _convertedGraph[realNode2].Terminal))
59+
{
60+
continue;
61+
}
62+
63+
break;
64+
}
65+
66+
Delta = 0;
67+
foreach (var neighbor in _convertedGraph[realNode1].Neighbors)
68+
{
69+
var neighborArrangementPosition = _dawgToArrangementPointer[neighbor.Key];
70+
71+
//var oldCost = Math.Abs(_swapIndex1 - neighborArrangementPosition) < CacheSize ? 0 : neighbor.Value;
72+
var oldCost = _swapIndex1/CacheSize == neighborArrangementPosition/CacheSize ? 0 : neighbor.Value;
73+
//var newCost = Math.Abs(_swapIndex2 - neighborArrangementPosition) < CacheSize ? 0 : neighbor.Value;
74+
var newCost = _swapIndex2/CacheSize == neighborArrangementPosition/CacheSize ? 0 : neighbor.Value;
75+
Delta += newCost - oldCost;
76+
}
77+
78+
foreach (var neighbor in _convertedGraph[realNode2].Neighbors)
79+
{
80+
var neighborArrangementPosition = _dawgToArrangementPointer[neighbor.Key];
81+
if (neighborArrangementPosition == _swapIndex1)
82+
{
83+
continue;
84+
}
85+
//var oldCost = Math.Abs(_swapIndex2 - neighborArrangementPosition) < CacheSize ? 0 : neighbor.Value;
86+
var oldCost = _swapIndex2/CacheSize == neighborArrangementPosition/CacheSize ? 0 : neighbor.Value;
87+
//var newCost = Math.Abs(_swapIndex1 - neighborArrangementPosition) < CacheSize ? 0 : neighbor.Value;
88+
var newCost = _swapIndex1/CacheSize == neighborArrangementPosition/CacheSize ? 0 : neighbor.Value;
89+
Delta += newCost - oldCost;
90+
}
91+
92+
return Delta;
93+
}
94+
95+
public void KeepLastMove()
96+
{
97+
Cost += Delta;
98+
99+
var realIndexOfSwap1 = _arrangementToDawgPointer[_swapIndex1];
100+
var realIndexOfSwap2 = _arrangementToDawgPointer[_swapIndex2];
101+
102+
_dawgToArrangementPointer[realIndexOfSwap1] = _swapIndex2;
103+
_dawgToArrangementPointer[realIndexOfSwap2] = _swapIndex1;
104+
_arrangementToDawgPointer[_swapIndex1] = realIndexOfSwap2;
105+
_arrangementToDawgPointer[_swapIndex2] = realIndexOfSwap1;
106+
}
107+
108+
public double Delta { get; private set; }
109+
110+
private int _swapIndex1;
111+
private int _swapIndex2;
112+
113+
private readonly List<UndirectedGraphNode> _convertedGraph;
114+
115+
private readonly CompressedSparseRowGraph _graph;
116+
public readonly int[] _arrangementToDawgPointer;
117+
private readonly int[] _dawgToArrangementPointer;
118+
119+
public CacheAwareInstance(CompressedSparseRowGraph graph)
120+
{
121+
_graph = graph;
122+
_convertedGraph = graph.Convert();
123+
_arrangementToDawgPointer = new int[_convertedGraph.Count];
124+
_dawgToArrangementPointer = new int[_convertedGraph.Count];
125+
for (var i = 0; i < _convertedGraph.Count; i++)
126+
{
127+
_arrangementToDawgPointer[i] = i;
128+
_dawgToArrangementPointer[i] = i;
129+
}
130+
131+
CalculateFullCost();
132+
}
133+
134+
private void CalculateFullCost()
135+
{
136+
Cost = _graph.CacheArrangementCost();
137+
}
138+
}
139+
}

0 commit comments

Comments
 (0)