From 7cc5a47d6a48f845600ead1296dd0eda506ef520 Mon Sep 17 00:00:00 2001 From: Austin Noska Date: Thu, 27 Jun 2019 10:57:00 -0400 Subject: [PATCH 1/4] feat: Added a hashset of visited nodes so bfs can be used on graphs --- ICD.Common.Utils/RecursionUtils.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ICD.Common.Utils/RecursionUtils.cs b/ICD.Common.Utils/RecursionUtils.cs index 826f35f..7f3c853 100644 --- a/ICD.Common.Utils/RecursionUtils.cs +++ b/ICD.Common.Utils/RecursionUtils.cs @@ -163,7 +163,7 @@ namespace ICD.Common.Utils } /// - /// Returns all of the nodes in the tree via breadth-first search. + /// Returns all of the nodes in the graph via breadth-first search. /// /// /// @@ -171,6 +171,7 @@ namespace ICD.Common.Utils /// private static IEnumerable BreadthFirstSearchIterator(T root, Func> getChildren) { + IcdHashSet visited = new IcdHashSet {root}; Queue process = new Queue(); process.Enqueue(root); @@ -179,8 +180,11 @@ namespace ICD.Common.Utils { yield return current; - foreach (T child in getChildren(current)) + foreach (T child in getChildren(current).Where(c => !visited.Contains(c))) + { + visited.Add(child); process.Enqueue(child); + } } } From 2d401959b651aeaf1330e9756bbe4a0b00f85a77 Mon Sep 17 00:00:00 2001 From: Austin Noska Date: Thu, 27 Jun 2019 10:57:55 -0400 Subject: [PATCH 2/4] feat: optimized get clique by using a bredth-first-search so it would not have to search the whole graph --- ICD.Common.Utils/RecursionUtils.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ICD.Common.Utils/RecursionUtils.cs b/ICD.Common.Utils/RecursionUtils.cs index 7f3c853..ad0e857 100644 --- a/ICD.Common.Utils/RecursionUtils.cs +++ b/ICD.Common.Utils/RecursionUtils.cs @@ -36,14 +36,18 @@ namespace ICD.Common.Utils /// Gets the clique containing the given node. /// /// - /// /// /// /// - public static IEnumerable GetClique(IEnumerable nodes, T node, Func> getAdjacent) + public static IEnumerable GetClique(T node, Func> getAdjacent) { - Dictionary> map = nodes.ToDictionary(n => n, getAdjacent); - return GetClique(map, node); + if (node == null) + throw new ArgumentNullException("node"); + + if (getAdjacent == null) + throw new ArgumentNullException("getAdjacent"); + + return BreadthFirstSearch(node, getAdjacent); } /// From e3f356a5db1fc2789cb5af132d6996c99eb8e59f Mon Sep 17 00:00:00 2001 From: Austin Noska Date: Thu, 27 Jun 2019 10:58:22 -0400 Subject: [PATCH 3/4] test: updating get cliques unit tests --- ICD.Common.Utils.Tests/RecursionUtilsTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ICD.Common.Utils.Tests/RecursionUtilsTest.cs b/ICD.Common.Utils.Tests/RecursionUtilsTest.cs index e50e025..ff96110 100644 --- a/ICD.Common.Utils.Tests/RecursionUtilsTest.cs +++ b/ICD.Common.Utils.Tests/RecursionUtilsTest.cs @@ -130,7 +130,7 @@ namespace ICD.Common.Utils.Tests [Test] public void GetCliqueSingleNodeTest() { - int[] clique = RecursionUtils.GetClique(s_CliqueGraph.Keys, 1, n => s_CliqueGraph[n]).ToArray(); + int[] clique = RecursionUtils.GetClique(1, n => s_CliqueGraph[n]).ToArray(); Assert.AreEqual(4, clique.Length); Assert.IsTrue(clique.Contains(1)); @@ -138,7 +138,7 @@ namespace ICD.Common.Utils.Tests Assert.IsTrue(clique.Contains(3)); Assert.IsTrue(clique.Contains(4)); - clique = RecursionUtils.GetClique(s_CliqueGraph.Keys, 5, n => s_CliqueGraph[n]).ToArray(); + clique = RecursionUtils.GetClique(5, n => s_CliqueGraph[n]).ToArray(); Assert.AreEqual(2, clique.Length); Assert.IsTrue(clique.Contains(5)); From 00e7fd6a6beac126586027e6c20fdef5739dae04 Mon Sep 17 00:00:00 2001 From: Austin Noska Date: Thu, 27 Jun 2019 11:00:03 -0400 Subject: [PATCH 4/4] docs: updating changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e10ace8..5d82b80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Added RecursionUtils method to get a single clique given a starting node + - Breadth First Search can now search graphs in addition to trees ### Changed - Fixed bug in IcdUriBuilder where Query property behaved differently to UriBuilder