private IEnumerable <GraphNode> SolveGraph(Dictionary <string, Dictionary <string, int> > graph) { GraphNode path = null; var open = new HashSetOrderedBy <GraphNode, int>((state) => state.Cost); var close = new HashSet <GraphNode>(); var keyToHash = new Dictionary <string, int>(); var hash = 1; foreach (var key in graph.Keys) { keyToHash.Add(key, hash); hash <<= 1; } var locationsToVisit = hash - 1; foreach (var location in graph.Keys) { var initState = new GraphNode { CurrentPos = location, LocationsToVisit = locationsToVisit - keyToHash[location], Cost = 0, }; open.Add(initState); } while (open.Any()) { var currentNode = open.ValueWithMinSelector(); var children = this.GenerateChildren(currentNode, graph, path, keyToHash); foreach (var child in children) { if (open.TryGetValue(child, out GraphNode existingNode) || close.TryGetValue(child, out existingNode)) { if (existingNode.Cost <= child.Cost) { continue; } open.Remove(existingNode); } open.Add(child); if (child.LocationsToVisit == 0) { path = child; var nodesToDelete = open.Where(n => n.Cost >= path.Cost).ToList(); foreach (var nd in nodesToDelete) { open.Remove(nd); } } } open.Remove(currentNode); close.Add(currentNode); yield return(currentNode); } yield return(path); }
private IEnumerable <GraphNode> GenerateChildren(GraphNode currentNode, Dictionary <string, Dictionary <string, int> > graph, GraphNode path, Dictionary <string, int> keyToHash) { foreach (var kvp in graph[currentNode.CurrentPos]) { if ((currentNode.LocationsToVisit & keyToHash[kvp.Key]) == 0) { continue; } var h = currentNode.Cost + kvp.Value; if (path != null && path.Cost < h) { continue; } yield return(new GraphNode { CurrentPos = kvp.Key, Cost = h, LocationsToVisit = currentNode.LocationsToVisit - keyToHash[kvp.Key], Parent = currentNode, }); } }
private IEnumerable <GraphNode> TSP(Dictionary <string, Dictionary <string, int> > graph, HashSet <string> visited, GraphNode currPos, int n, int count, GraphNode ans) { if (count == n) { if (ans.Cost < currPos.Cost) { ans.Parent = currPos.Parent; ans.Cost = currPos.Cost; ans.CurrentPos = currPos.CurrentPos; } yield break; } if (currPos == null) { foreach (var nextLocation in graph.Keys) { visited.Add(nextLocation); var next = new GraphNode { Parent = currPos, Cost = 0, CurrentPos = nextLocation, }; foreach (var innerNodes in this.TSP(graph, visited, next, n, count + 1, ans)) { yield return(innerNodes); } visited.Remove(nextLocation); } } else { foreach (var nextLocation in graph[currPos.CurrentPos].Keys) { if (!visited.Contains(nextLocation)) { visited.Add(nextLocation); var next = new GraphNode { Parent = currPos, Cost = currPos.Cost + graph[currPos.CurrentPos][nextLocation], CurrentPos = nextLocation, }; yield return(next); foreach (var innerNodes in this.TSP(graph, visited, next, n, count + 1, ans)) { yield return(innerNodes); } visited.Remove(nextLocation); } } } }