public void TestGetPath() { var nodes = new Node[10]; for (var i = 0; i < nodes.Length; i++) { var node = new Node(i); nodes[i] = node; if (i <= 0) continue; nodes[i - 1].Next = node; node.Previous = nodes[i - 1]; } var path = nodes.GetPath(); var res = path.ToList(); Assert.That(res[0], Is.EqualTo(0)); for (var i = 1; i < res.Count; i++) { Assert.That(res[i], Is.EqualTo(i)); } }
private static Node[] CreteNodesAndDistancesForSIngle2Opt(out double[][] distances) { var nodes = new Node[4]; for (var i = 0; i < nodes.Length; i++) { var node = new Node(i); nodes[i] = node; if (i <= 0) continue; nodes[i - 1].Next = node; node.Previous = nodes[i - 1]; } const int a = 0, b = 1, d = 3, c = 2; distances = new double[nodes.Length][]; distances[a] = new double[nodes.Length]; distances[b] = new double[nodes.Length]; distances[c] = new double[nodes.Length]; distances[d] = new double[nodes.Length]; distances[a][b] = 1; distances[b][d] = 1; distances[d][c] = 1; distances[b][a] = 1; distances[d][b] = 1; distances[c][d] = 1; distances[a][d] = 0.5; distances[d][a] = 0.5; distances[b][c] = 0.5; distances[c][b] = 0.5; return nodes; }
public Node(int index, Node previous) : this(index) { Previous = previous; }
public static void TwoOpt(Node a, Node c, double[][] distances) { //if either of seeds is end of path if (a == null || c == null) return; if (a.Next == null || c.Next == null) return; var b = a.Next; var d = c.Next; var ab = distances[a.Index][b.Index]; var cd = distances[c.Index][d.Index]; var ad = distances[a.Index][d.Index]; var bc = distances[b.Index][c.Index]; var abcd = ab + cd; var adbc = ad + bc; if (adbc > abcd) return; c.ToggleDirection(); b.Next?.ToggleDirection(); a.Next = c; c.Next = c.Previous; c.Previous = a; b.Previous = b.Next; b.Next = d; d.Previous = b; }
public static void RandomTwoOpt(Node[] path, double[][] distances) { var r = new Random(4711); for (var i = 0; i < 20*Math.Pow(10, 6); i++) { var a = path[r.Next(path.Length)]; var c = path[r.Next(path.Length)]; TwoOpt(a, c, distances); } }
public static Node[] RandomApprox(int n) { var nodes = new Node[n]; var visited = new HashSet<int>(); var r = new Random(4711); for (var i = 0; i < n; i++) { int index; while (!visited.Add(index = r.Next(n))); nodes[i] = new Node(index); if (i <= 0) continue; nodes[i].Previous = nodes[i - 1]; nodes[i - 1].Next = nodes[i]; } nodes[0].Previous = nodes.Last(); nodes.Last().Next = nodes[0]; return nodes; }
public static Node[] Greedy(IReadOnlyCollection<Coordinate> coordinates, double[][] distances) { var r = new Random(5); var current = r.Next(coordinates.Count); var visited = new HashSet<int>(); var path = new List<Node> {new Node(current)}; while(path.Count < coordinates.Count) { var i = current; var closest = distances[i].SkipIndices(visited).ToList().IndexOfMin(); var closestNode = new Node(i, path.Last()); path.Last().Next = closestNode; path.Add(closestNode); current = closest; visited.Add(i); } return path.ToArray(); }