-
Notifications
You must be signed in to change notification settings - Fork 0
/
SteinerTreeKMBApprox.cs
154 lines (123 loc) · 5.18 KB
/
SteinerTreeKMBApprox.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
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Threading.Tasks;
namespace SteinerTreeProblem
{
class SteinerTreeKMBApprox
{
private int[,] distanceMatrix;
private int[,] predecessorMatrix;
private Hashtable paths;
private Graph graph;
private ParallelOptions options;
private int length;
// ---------------- Getter and Setter ------------------
public int getLength()
{
return this.length;
}
public void savePath(List<int> terminals, List<int[]> path, int length)
{
// create key for storing steinertree
terminals.Sort();
string key = String.Join("-", terminals);
Tuple<List<int[]>, int> values = Tuple.Create(path, length);
if (!paths.ContainsKey(key)) paths.Add(key,values);
else paths[key] = values;
}
public Tuple<List<int[]>, int> getPath(List<int> terminals)
{
// create key for finding steinertree
terminals.Sort();
string key = String.Join("-", terminals);
Tuple<List<int[]>, int> values;
if (paths.ContainsKey(key)){
values = (Tuple<List<int[]>, int>)this.paths[key];
} else {
List<int[]> tree = new List<int[]>();
values = Tuple.Create(tree, int.MaxValue);
}
return values;
}
// ---------------- Constructors ------------------
public SteinerTreeKMBApprox(Graph graph, ParallelOptions options)
{
this.graph = graph;
this.options = options;
paths = new Hashtable();
}
// ---------------- Functions ------------------
public List<int[]> approxMinimumSteinerTree(List<int> terminals)
{
this.graph.setTerminals(terminals);
return(approxMinimumSteinerTree());
}
public List<int[]> approxMinimumSteinerTree()
{
List<int[]> edges = graph.getEdges();
List<int> terminals = graph.getTerminals();
List<int> nodes = graph.getNodes();
length = 0;
// Create Instance of Dijkstra Algorithm
graph.calculateDistanceMatrixTerminals(this.options);
distanceMatrix = graph.getDistanceMatrix();
predecessorMatrix = graph.getPredecessorMatrix();
// Create Distance Network -------------------------------------
// save nodes of shortest paths as steinertree
this.extractShortestPath();
// create a new graph as full distance Network
Graph distanceNetwork = new Graph(distanceMatrix, graph.getTerminals());
// create Instance of Prims Mimumim Spannign Tree Algorithm
List<int[]> mstList = distanceNetwork.solveMinimumSpanningTree();
// Replace Edges with the actual Path -------------------------
List<int[]> steinerTree = new List<int[]>();
foreach(int[] edge in mstList)
{
terminals = new List<int>() {edge[0], edge[1]};
steinerTree = steinerTree.Concat(getPath(terminals).Item1).Distinct().ToList();
length = length + edge[2];
//Console.WriteLine( edge[0] + " " + edge[1] + " " + edge[2]);
}
Graph graphMst = new Graph(steinerTree, this.graph.getTerminals());
//graphMst.printAllEdges();
graphMst.solveMinimumSpanningTree();
List<int[]> edgeList = graphMst.pruneTree();
this.length = graphMst.getLength();
return edgeList;
}
public void extractShortestPath()
{
// init variables
List<int> currentTerminals;
List<int[]> path;
int n = this.graph.getNodes().Count();
// Shortest Path from every root node ...
//for(int i = 1; i <= n; i++)
foreach(int i in graph.getTerminals())
{
// to every other point
foreach(int j in graph.getTerminals())
{
// init list for all nodes in the steiner tree
path = new List<int[]>();
// set destination point as startin gpoint for backtracking
int predecessor = j;
// backtrack to root point i
while(i != predecessor)
{
path.Add(new int[] {predecessor, this.predecessorMatrix[i,predecessor], graph.getWeight(predecessor,this.predecessorMatrix[i,predecessor])});
predecessor = this.predecessorMatrix[i,predecessor];
}
// write terminals in a list
currentTerminals = new List<int>() {i, j};
// save path
savePath(currentTerminals, path, this.distanceMatrix[i,j]);
//break;
}
//break;
}
}
}
}