public void DijkstraUnconnected() { // 0 -- 1 2 -- 3 // | / // | / // 4 -- 5 bool[,] graph2 = { { false, true, false, false, false, false }, { true, false, false, false, false, false }, { false, false, false, true, false, true }, { false, false, true, false, false, true }, { false, false, false, false, false, true }, { false, false, true, true, true, false }, }; SearchGraph searchGraph2 = SearchGraphFromData(graph2); Dictionary <int, GraphNode> graphNodes2 = GetGraphNodesIdIndex(searchGraph2); var mstNodes2 = new List <GraphNode> { graphNodes2[0], graphNodes2[2], graphNodes2[4], graphNodes2[3] }; var distances = new DistanceLookup(graphNodes2.Values.ToArray()); Assert.IsNull(distances.GetShortestPath(mstNodes2[0].DistancesIndex, mstNodes2[3].DistancesIndex)); }
public void DijkstraUnconnected() { // 0 -- 1 2 -- 3 // | / // | / // 4 -- 5 bool[,] graph2 = { { false, true, false, false, false, false }, { true, false, false, false, false, false }, { false, false, false, true, false, true }, { false, false, true, false, false, true }, { false, false, false, false, false, true }, { false, false, true, true, true, false }, }; SearchGraph searchGraph2 = SearchGraphFromData(graph2); Dictionary <int, GraphNode> graphNodes2 = GetGraphNodesIdIndex(searchGraph2); var mstNodes2 = new List <GraphNode> { graphNodes2[0], graphNodes2[2], graphNodes2[4], graphNodes2[3] }; var distances = new DistanceLookup(); try { var _ = distances[mstNodes2[0], mstNodes2[3]]; } catch (GraphNotConnectedException) { return; } Assert.Fail("No exception thrown for disconnected graph"); }
/// <summary> /// Preprocesses the SkillTree graph into a simplified graph that omits /// nodes (single pass) and contracts all skilled nodes into a single node. /// </summary> private void BuildSearchGraph() { // Make all directed edges from Scion Ascendant "Path of the ..." node undirected. // This is really dirty but the whole code is so dependant on the skill tree stuff that // I don't see a non dirty way. var ascendantClassStartNodes = SkillTree.Skillnodes.Values.Where(SkillTree.IsAscendantClassStartNode).ToList(); foreach (var classStartNode in ascendantClassStartNodes) { foreach (var neighbor in classStartNode.Neighbor) { neighbor.Neighbor.Add(classStartNode); } } var searchGraph = new SearchGraph(); CreateStartNodes(searchGraph); CreateTargetNodes(searchGraph); CreateSearchGraph(searchGraph); AllNodes = searchGraph.NodeDict.Values.ToList(); // Remove all added edges again. foreach (var classStartNode in ascendantClassStartNodes) { foreach (var neighbor in classStartNode.Neighbor) { neighbor.Neighbor.Remove(classStartNode); } } }
/// <summary> /// Initializes <see cref="TargetNodes"/> with all check-tagged nodes and the start node. /// Adds the check-tagged nodes to the provided SearchGraph. /// </summary> private void CreateTargetNodes(SearchGraph searchGraph) { TargetNodes = (from node in Settings.Checked where !searchGraph.NodeDict.ContainsKey(node) select searchGraph.AddNodeId(node.Id)) .Union(new[] { StartNode }).ToList(); }
// Builds a graph from an adjacency matrix. // Only the lower left half is checked. SearchGraph SearchGraphFromData(bool[,] adjacencyMatrix) { int n = adjacencyMatrix.GetUpperBound(0) + 1; // Don't screw this up. Assert.IsTrue(n == adjacencyMatrix.GetUpperBound(1) + 1); List<SkillNode> nodes = new List<SkillNode>(); for (int i = 0; i < n; i++) { SkillNode node = new SkillNode(); node.Id = (ushort)i; nodes.Add(node); } for (int i = 0; i < n; i++) { nodes[i].Neighbor = new List<SkillNode>(); for (int j = 0; j < i; j++) { if (adjacencyMatrix[i, j]) { nodes[i].Neighbor.Add(nodes[j]); // No directed edges atm. nodes[j].Neighbor.Add(nodes[i]); } } } SearchGraph graph = new SearchGraph(); foreach (SkillNode node in nodes) { graph.AddNode(node); } return graph; }
public void TestDijkstra() { // TODO: Maybe make the graphs class members. /// 0 -- 1 -- 2 -- 3 /// \ | / /// \ | / /// 4 -- 5 bool[,] graph1 = { { false, true, false, false, true, false }, { true, false, true, false, false, false }, { false, true, false, true, false, true }, { false, false, true, false, false, true }, { true, false, false, false, false, true }, { false, false, true, true, true, false }, }; SearchGraph searchGraph1 = SearchGraphFromData(graph1); Dictionary <int, GraphNode> graphNodes = GetGraphNodesIdIndex(searchGraph1); DistanceLookup distanceLookup = new DistanceLookup(); Assert.IsTrue(distanceLookup.GetDistance(graphNodes[0], graphNodes[0]) == 0, "Failed 0 distance test"); Assert.IsTrue(distanceLookup.GetDistance(graphNodes[0], graphNodes[5]) == 2, "Wrong distance"); Assert.IsTrue(distanceLookup.GetDistance(graphNodes[0], graphNodes[3]) == 3, "Wrong distance"); }
/// <summary> /// Preprocesses the SkillTree graph into a simplified graph that omits /// nodes (single pass) and contracts all skilled nodes into a single node. /// </summary> private void BuildSearchGraph() { // Make all directed edges from Scion Ascendant "Path of the ..." node undirected. // This is really dirty but the whole code is so dependant on the skill tree stuff that // I don't see a non dirty way. var ascendantClassStartNodes = SkillTree.Skillnodes.Values.Where(SkillTree.IsAscendantClassStartNode).ToList(); foreach (var classStartNode in ascendantClassStartNodes) { foreach (var neighbor in classStartNode.Neighbor) { neighbor.Neighbor.Add(classStartNode); } } _searchGraph = new SearchGraph(); CreateStartNodes(); CreateTargetNodes(); // Set start and target nodes as the fixed nodes. _fixedNodes = new HashSet <ushort>(StartNodes.Nodes); _fixedNodes.UnionWith(_targetNodes.Select(node => node.Id)); OnStartAndTargetNodesCreated(); CreateSearchGraph(); // Remove all added edges again. foreach (var classStartNode in ascendantClassStartNodes) { foreach (var neighbor in classStartNode.Neighbor) { neighbor.Neighbor.Remove(classStartNode); } } }
public void TestDijkstra() { // 0 -- 1 -- 2 -- 3 // \ | / // \ | / // 4 -- 5 bool[,] graph1 = { { false, true, false, false, true, false }, { true, false, true, false, false, false }, { false, true, false, true, false, true }, { false, false, true, false, false, true }, { true, false, false, false, false, true }, { false, false, true, true, true, false }, }; SearchGraph searchGraph1 = SearchGraphFromData(graph1); Dictionary <int, GraphNode> graphNodes = GetGraphNodesIdIndex(searchGraph1); DistanceLookup distanceLookup = new DistanceLookup(graphNodes.Values.ToList()); Assert.AreEqual((uint)0, distanceLookup[graphNodes[0].DistancesIndex, graphNodes[0].DistancesIndex], "Failed 0 distance test"); Assert.AreEqual((uint)2, distanceLookup[graphNodes[0].DistancesIndex, graphNodes[5].DistancesIndex], "Wrong distance"); Assert.AreEqual((uint)3, distanceLookup[graphNodes[0].DistancesIndex, graphNodes[3].DistancesIndex], "Wrong distance"); }
Dictionary<int, GraphNode> GetGraphNodesIdIndex(SearchGraph graph) { Dictionary<int, GraphNode> retval = new Dictionary<int, GraphNode>(); foreach (GraphNode node in graph.NodeDict.Values) { retval.Add(node.Id, node); } return retval; }
Dictionary <int, GraphNode> GetGraphNodesIdIndex(SearchGraph graph) { Dictionary <int, GraphNode> retval = new Dictionary <int, GraphNode>(); foreach (GraphNode node in graph.NodeDict.Values) { retval.Add(node.Id, node); } return(retval); }
/// <summary> /// Preprocesses the SkillTree graph into a simplified graph that omits /// nodes (single pass) and contracts all skilled nodes into a single node. /// </summary> private void BuildSearchGraph() { _searchGraph = new SearchGraph(); CreateStartNodes(); CreateTargetNodes(); // Set start and target nodes as the fixed nodes. _fixedNodes = new HashSet <ushort>(StartNodes.Nodes); _fixedNodes.UnionWith(_targetNodes.Select(node => node.Id)); OnStartAndTargetNodesCreated(); CreateSearchGraph(); }
/// <summary> /// Initializes <see cref="StartNode"/> and sets the start node in the provided SearchGraph. /// </summary> private void CreateStartNodes(SearchGraph searchGraph) { if (Settings.SubsetTree.Count > 0 || Settings.InitialTree.Count > 0) { // if the current tree does not need to be part of the result, only skill the character node StartNode = searchGraph.SetStartNodes(new[] { _tree.GetCharNode() }); } else { StartNode = searchGraph.SetStartNodes(_tree.SkilledNodes); } }
public void TestMST() { // 0 -- 1 -- 2 -- 3 // \ | / // \ | / // 4 -- 5 -- 6 -- 7 bool[,] graph1 = { { false, true, false, false, true, false, false, false }, { true, false, true, false, false, false, false, false }, { false, true, false, true, false, true, false, false }, { false, false, true, false, false, true, false, false }, { true, false, false, false, false, true, false, false }, { false, false, true, true, true, false, true, false }, { false, false, false, false, false, true, false, true }, { false, false, false, false, false, false, true, false }, }; SearchGraph searchGraph1 = SearchGraphFromData(graph1); Dictionary <int, GraphNode> graphNodes1 = GetGraphNodesIdIndex(searchGraph1); var distances = new DistanceLookup(); var mstNodes1 = new List <GraphNode> { graphNodes1[3], graphNodes1[5], graphNodes1[7], graphNodes1[0] }; distances.CalculateFully(mstNodes1); MinimalSpanningTree mst1 = new MinimalSpanningTree(mstNodes1, distances); mst1.Span(graphNodes1[0]); Assert.AreEqual(3, mst1.SpanningEdges.Count, "Wrong amount of spanning edges"); var goalEdges = new [] { new [] { 0, 5 }, new [] { 5, 3 }, new [] { 5, 7 } }; foreach (var edge in goalEdges) { Assert.AreEqual(1, mst1.SpanningEdges.Count( e => (e.Inside.Id == edge[0] && e.Outside.Id == edge[1]) || (e.Inside.Id == edge[1] && e.Outside.Id == edge[0])), "Edge " + edge + " not contained exactly once."); } Assert.AreEqual(6, mst1.GetUsedNodes().Count, "Wrong MST length"); }
/// <summary> /// Задание 3 /// </summary> private static void Task3() { CL.BeginApp("Функция обхода графа в ширину"); string filename = @"..\..\..\TxtFiles\WorkMatrix.txt"; int[,] matrix = ReadMatrix.Read(filename); CL.PrintArr(matrix); SearchGraph search = new SearchGraph(); search.BFS(matrix); //SearchGraph.BFS(matrix); CL.ConsolePause(); Menu(); }
public void TestMST() { // 0 -- 1 -- 2 -- 3 // \ | / // \ | / // 4 -- 5 -- 6 -- 7 bool[,] graph1 = { { false, true, false, false, true, false, false, false }, { true, false, true, false, false, false, false, false }, { false, true, false, true, false, true, false, false }, { false, false, true, false, false, true, false, false }, { true, false, false, false, false, true, false, false }, { false, false, true, true, true, false, true, false }, { false, false, false, false, false, true, false, true }, { false, false, false, false, false, false, true, false }, }; SearchGraph searchGraph1 = SearchGraphFromData(graph1); Dictionary <int, GraphNode> graphNodes1 = GetGraphNodesIdIndex(searchGraph1); var mstNodes1 = new List <GraphNode> { graphNodes1[3], graphNodes1[5], graphNodes1[7], graphNodes1[0] }; var distances = new DistanceLookup(mstNodes1); var mst1 = new MinimalSpanningTree(mstNodes1.Select(n => n.DistancesIndex).ToList(), distances); mst1.Span(graphNodes1[0].DistancesIndex); Assert.AreEqual(3, mst1.SpanningEdges.Count, "Wrong amount of spanning edges"); var goalEdges = new[] { new [] { 0, 5 }, new [] { 5, 3 }, new [] { 5, 7 } }; foreach (var edge in goalEdges) { Assert.AreEqual(1, mst1.SpanningEdges.Select(e => new Tuple <ushort, ushort>(distances.IndexToNode(e.Inside).Id, distances.IndexToNode(e.Outside).Id)).Count( t => (t.Item1 == edge[0] && t.Item2 == edge[1]) || (t.Item1 == edge[1] && t.Item2 == edge[0])), "Edge " + edge + " not contained exactly once."); } }
protected internal virtual void localStart() { SearchGraph searchGraph = this.linguist.getSearchGraph(); this.currentFrameNumber = 0; this.curTokensScored.value = (double)0f; this.numStateOrder = searchGraph.getNumStateOrder(); this.activeListManager.setNumStateOrder(this.numStateOrder); if (this.buildWordLattice) { this.loserManager = new AlternateHypothesisManager(this.maxLatticeEdges); } SearchState initialState = searchGraph.getInitialState(); this.activeList = this.activeListManager.getEmittingList(); this.activeList.add(new Token(initialState, -1L)); this.clearCollectors(); this.growBranches(); this.growNonEmittingBranches(); }
// Builds a graph from an adjacency matrix. // Only the lower left half is checked. private static SearchGraph SearchGraphFromData(bool[,] adjacencyMatrix) { int n = adjacencyMatrix.GetUpperBound(0) + 1; // Don't screw this up. Assert.IsTrue(n == adjacencyMatrix.GetUpperBound(1) + 1); List <SkillNode> nodes = new List <SkillNode>(); for (ushort i = 0; i < n; i++) { var node = new SkillNode { Id = i }; nodes.Add(node); } for (int i = 0; i < n; i++) { nodes[i].Neighbor = new List <SkillNode>(); for (int j = 0; j < i; j++) { if (adjacencyMatrix[i, j]) { nodes[i].Neighbor.Add(nodes[j]); // No directed edges atm. nodes[j].Neighbor.Add(nodes[i]); } } } SearchGraph graph = new SearchGraph(); foreach (SkillNode node in nodes) { graph.AddNode(node); } return(graph); }
// Builds a graph from an adjacency matrix. // Only the lower left half is checked. private static SearchGraph SearchGraphFromData(bool[,] adjacencyMatrix) { int n = adjacencyMatrix.GetUpperBound(0) + 1; // Don't screw this up. Assert.IsTrue(n == adjacencyMatrix.GetUpperBound(1) + 1); List <PassiveNodeViewModel> nodes = new List <PassiveNodeViewModel>(); for (ushort i = 0; i < n; i++) { var node = new PassiveNodeViewModel(i); nodes.Add(node); } for (int i = 0; i < n; i++) { for (int j = 0; j < i; j++) { if (adjacencyMatrix[i, j]) { nodes[i].NeighborPassiveNodes[nodes[j].Id] = nodes[j]; // No directed edges atm. nodes[j].NeighborPassiveNodes[nodes[i].Id] = nodes[i]; } } } SearchGraph graph = new SearchGraph(); foreach (PassiveNodeViewModel node in nodes) { graph.AddNode(node); } return(graph); }
/// <summary> /// Initializes the search graph by going through all node groups /// of the skill tree and including those that could be part of the solution. /// </summary> private void CreateSearchGraph(SearchGraph searchGraph) { foreach (var ng in SkillTree.NodeGroups) { var mustInclude = false; SkillNode firstNeighbor = null; // Find out if this node group can be omitted. foreach (var node in ng.Nodes) { // If the group contains a skilled node or a target node, // it can't be omitted. if (searchGraph.NodeDict.ContainsKey(node) || MustIncludeNodeGroup(node)) { mustInclude = true; break; } // If the group is adjacent to more than one node, it must // also be fully included (since it's not isolated and could // be part of a path to other nodes). var ng1 = ng; foreach (var neighbor in node.Neighbor.Where(neighbor => neighbor.SkillNodeGroup != ng1)) { if (firstNeighbor == null) { firstNeighbor = neighbor; } // Does the group have more than one neighbor? if (neighbor != firstNeighbor) { mustInclude = true; break; } } if (mustInclude) { break; } } if (mustInclude) { // Add the group's nodes individually foreach (var node in ng.Nodes) { // Can't path through class starts. if (node.IsRootNode // Don't add nodes that are already in the graph (as // target or start nodes). || searchGraph.NodeDict.ContainsKey(node) // Don't add nodes that should not be skilled. || Settings.Crossed.Contains(node) // Mastery nodes are obviously not useful. || node.Type == PassiveNodeType.Mastery // Ignore ascendancies for now || node.ascendancyName != null) { continue; } if (IncludeNodeInSearchGraph(node)) { searchGraph.AddNode(node); } } } } }
public void TestMST() { /// 0 -- 1 -- 2 -- 3 /// \ | / /// \ | / /// 4 -- 5 -- 6 -- 7 bool[,] graph1 = { { false, true, false, false, true, false, false, false }, { true, false, true, false, false, false, false, false }, { false, true, false, true, false, true, false, false }, { false, false, true, false, false, true, false, false }, { true, false, false, false, false, true, false, false }, { false, false, true, true, true, false, true, false }, { false, false, false, false, false, true, false, true }, { false, false, false, false, false, false, true, false }, }; SearchGraph searchGraph1 = SearchGraphFromData(graph1); Dictionary <int, GraphNode> graphNodes1 = GetGraphNodesIdIndex(searchGraph1); DistanceLookup distanceLookup = new DistanceLookup(); HashSet <GraphNode> mstNodes1 = new HashSet <GraphNode> { graphNodes1[3], graphNodes1[5], graphNodes1[7] }; MinimalSpanningTree mst1 = new MinimalSpanningTree(mstNodes1); mst1.Span(startFrom: graphNodes1[0]); Assert.IsTrue(mst1.SpanningEdges.Count == 3, "Wrong amount of spanning edges"); /// This can fail even if the mst would be valid! The test only works for /// the current implementation of the mst algorithm, but I can't find a /// better way to do this with the current data structures... Assert.IsTrue(mst1.SpanningEdges[0].inside.Id == 0 && mst1.SpanningEdges[0].outside.Id == 5, "First edge is wrong"); Assert.IsTrue(mst1.SpanningEdges[1].inside.Id == 5 && mst1.SpanningEdges[1].outside.Id == 3, "Second edge is wrong"); Assert.IsTrue(mst1.SpanningEdges[2].inside.Id == 5 && mst1.SpanningEdges[2].outside.Id == 7, "Third edge is wrong"); Assert.IsTrue(mst1.UsedNodeCount == 5, "Wrong MST length"); /// Test unconnected graph /// 0 -- 1 2 -- 3 /// | / /// | / /// 4 -- 5 bool[,] graph2 = { { false, true, false, false, false, false }, { true, false, false, false, false, false }, { false, false, false, true, false, true }, { false, false, true, false, false, true }, { false, false, false, false, false, true }, { false, false, true, true, true, false }, }; SearchGraph searchGraph2 = SearchGraphFromData(graph2); Dictionary <int, GraphNode> graphNodes2 = GetGraphNodesIdIndex(searchGraph2); HashSet <GraphNode> mstNodes2 = new HashSet <GraphNode> { graphNodes2[0], graphNodes2[2], graphNodes2[4] }; bool pass = false; try { MinimalSpanningTree mst = new MinimalSpanningTree(mstNodes2); mst.Span(graphNodes2[3]); } catch (DistanceLookup.GraphNotConnectedException) { pass = true; } Assert.IsTrue(pass, "No exception thrown for disconnected graph"); }
/// <summary> /// Initializes <see cref="StartNode"/> and sets the start node in the provided SearchGraph. /// </summary> private void CreateStartNodes(SearchGraph searchGraph) { StartNode = searchGraph.SetStartNodes(_tree.SkilledNodes); }
private static Dictionary <ushort, GraphNode> GetGraphNodesIdIndex(SearchGraph graph) => graph.NodeDict.Values.ToDictionary(n => n.Id);