コード例 #1
0
ファイル: Node.cs プロジェクト: pauldambra/treeFilter
        public static Node BreadthFirstDeletion(Node startNode, HashSet<int> allIncludedNodes, 
            int[] explicitlyIncludedNodes)
        {
            var stack = new Stack<Node>();
            stack.Push(startNode);
            while (stack.Count != 0)
            {
                var current = stack.Pop();

                if (allIncludedNodes.Contains(current.Id))
                {
                    MarkNodeInclusionType(explicitlyIncludedNodes, current);
                    RemoveExcludedParents(allIncludedNodes, current.Parents);

                    foreach (var child in current.Children)
                    {
                        stack.Push(child);
                    }
                }
                else
                {
                    RemoveNodeFromTheTree(current);
                }
            }
            return startNode;
        }
コード例 #2
0
        public static NodeClosures Analyse(Node root)
        {
            var results = new NodeClosures
                              {
                                  AncestorClosures = new Dictionary<int, HashSet<int>>(),
                                  DescendantClosures = new Dictionary<int, HashSet<int>>()
                              };
            //walk the tree and build the closures lists
            var stack = new Stack<Node>();
            stack.Push(root);

            var route = new Stack<Node>();

            while (stack.Count != 0)
            {
                var current = stack.Pop();

                while (route.Any() && !route.Peek().Children.Any(n => n.Id == current.Id))
                {
                    route.Pop();
                }
                route.Push(current);

                AddNodeRelationships(results, current, route);
                foreach (var child in current.Children)
                {
                    stack.Push(child);
                }
            }
            return results;
        }
コード例 #3
0
ファイル: GraphBuilder.cs プロジェクト: pauldambra/treeFilter
        public static dynamic BuildLargeGraph(int depth, int levelMaxSiblings)
        {
            var id = 0;
            var builtLevel = 0;

            var root = new Node {Id = id++};
            var queue = new Queue<Node>(100000000);
            queue.Enqueue(root);

            while (builtLevel < depth)
            {
                var nextQueue = new Queue<Node>();
                while (queue.Count != 0)
                {
                    var node = queue.Dequeue();
                    var max = Random.Next(1, levelMaxSiblings);
                    for (var siblingCount = 0; siblingCount < max; siblingCount++)
                    {
                        nextQueue.Enqueue(Node.CreateNode(id++, node));
                    }
                }
                queue = nextQueue;
                builtLevel++;
            }

            return new {MaxId = id, Tree = root};
        }
コード例 #4
0
 private static void AddNodeRelationships(NodeClosures results, Node current, IEnumerable<Node> route)
 {
     foreach (var node in route)
     {
         results.AncestorClosures.GetOrCreateValuesList(current.Id).Add(node.Id);
         results.DescendantClosures.GetOrCreateValuesList(node.Id).Add(current.Id);
     }
 }
コード例 #5
0
ファイル: GraphBuilder.cs プロジェクト: pauldambra/treeFilter
        /// <summary>
        ///                     0
        ///                   / | \
        ///                  1  2  3
        ///                 / \    |
        ///                4   5   6
        ///               /     \ / \
        ///              7       8   9
        ///                          |
        ///                          10
        /// </summary>
        public static Node BuildExampleGraph()
        {
            var root = new Node {Id = 0};

            var one = Node.CreateNode(1, root);
            Node.CreateNode(2, root);
            var three = Node.CreateNode(3, root);

            var four = Node.CreateNode(4, one);
            var five = Node.CreateNode(5, one);
            var six = Node.CreateNode(6, three);

            Node.CreateNode(7, four);
            var eight = Node.CreateNode(8, five);
            eight.Parents.Add(six);
            six.Children.Add(eight);

            var nine = Node.CreateNode(9, six);
            Node.CreateNode(10, nine);

            return root;
        }
コード例 #6
0
 public void CanDeleteNodes()
 {
     _root.FirstOrDefaultDescendant(n => n.Id == 6).IsExplicitlyIncluded = true;
     foreach (var i in new []{0, 3, 8, 9, 10})
     {
         var capturedId = i;
         _root.FirstOrDefaultDescendant(n => n.Id == capturedId).IsImplicitlyIncluded = true;
     }
     _root = Node.BreadthFirstDeletion(_root, new HashSet<int>{0,3,6,8,9,10}, new []{6});
     var removedNodes = new[] { 1, 2, 4, 5, 7 };
     foreach (var id in removedNodes)
     {
         var capturedId = id;
         _root.FirstOrDefaultDescendant(n => n.Id == capturedId).Should().BeNull();
     }
     var keptNodes = new[] { 0, 3, 6, 8, 9, 10 };
     foreach (var id in keptNodes)
     {
         var capturedId = id;
         var match = _root.FirstOrDefaultDescendant(n => n.Id == capturedId);
         match.Should().NotBeNull();
         match.IsExplicitlyIncluded.Should().Be(match.Id == 6);
     }
 }
コード例 #7
0
 public void Setup()
 {
     _root = GraphBuilder.BuildExampleGraph();
 }
コード例 #8
0
ファイル: Node.cs プロジェクト: pauldambra/treeFilter
 public static Node CreateNode(int id, Node parent)
 {
     var n = new Node { Id = id };
     parent.Children.Add(n);
     n.Parents.Add(parent);
     return n;
 }
コード例 #9
0
ファイル: Node.cs プロジェクト: pauldambra/treeFilter
 private static void RemoveNodeFromTheTree(Node current)
 {
     for (var i = 0; i < current.Parents.Count; i++)
     {
         var parent = current.Parents.ElementAt(i);
         parent.Children.Remove(current);
     }
 }
コード例 #10
0
ファイル: Node.cs プロジェクト: pauldambra/treeFilter
        private static void ProcessParents(Node template, Node clone, Node root)
        {
            var stack = new Stack<Node>();
            foreach (var parent in template.Parents)
            {
                stack.Push(parent);
            }
            while (stack.Count != 0)
            {
                var current = stack.Pop();
                Node targetParent;

                if (root == null)
                {
                    targetParent = new Node {Id = current.Id};
                }
                else
                {
                    targetParent = root.FirstOrDefaultDescendant(n => n.Id == current.Id) ?? new Node { Id = current.Id };
                }

                clone.Parents.Add(targetParent);
                targetParent.Children.Add(clone);
                ProcessParents(current, targetParent, root);
            }
        }
コード例 #11
0
ファイル: Node.cs プロジェクト: pauldambra/treeFilter
 private static void ProcessChildren(Node templateParent, Node copyParent)
 {
     var stack = new Stack<Node>();
     foreach (var child in templateParent.Children)
     {
         stack.Push(child);
     }
     while (stack.Count != 0)
     {
         var template = stack.Pop();
         var copy = new Node { Id = template.Id };
         copy.Parents.Add(copyParent);
         copyParent.Children.Add(copy);
         ProcessChildren(template, copy);
     }
 }
コード例 #12
0
ファイル: Node.cs プロジェクト: pauldambra/treeFilter
 private static void MarkNodeInclusionType(IEnumerable<int> explicitlyIncludedNodes, Node current)
 {
     if (explicitlyIncludedNodes.Contains(current.Id))
     {
         current.IsExplicitlyIncluded = true;
     }
     else
     {
         current.IsImplicitlyIncluded = true;
     }
 }
コード例 #13
0
ファイル: Node.cs プロジェクト: pauldambra/treeFilter
 protected bool Equals(Node other)
 {
     return Id == other.Id;
 }
コード例 #14
0
ファイル: Node.cs プロジェクト: pauldambra/treeFilter
 public Node CloneBranch()
 {
     var n = new Node {Id = Id};
     ProcessChildren(this, n);
     return n;
 }
コード例 #15
0
ファイル: Node.cs プロジェクト: pauldambra/treeFilter
 public Node CloneAncestors(Node clone, Node root)
 {
     ProcessParents(this, clone, root);
     return clone.FirstOrDefaultAncestor(n => n.Parents.Count == 0);
 }
コード例 #16
0
ファイル: Node.cs プロジェクト: pauldambra/treeFilter
        /// <summary>
        /// Partial Bottom Up Breadth first search for nodes which are neither explicitly nor implicitly included
        /// </summary>
        public static Node Filter(Node startNode, IEnumerable<int> includedNodes)
        {
            var explicitlyIncludedNodes = startNode.DescendantsWhere(n => includedNodes.Contains(n.Id)).ToArray();

            if (!explicitlyIncludedNodes.Any())
            {
                return null;
            }

            var closures = NodeClosureAnalyser.Analyse(startNode);
            var results = new HashSet<int>();
            foreach (var node in explicitlyIncludedNodes)
            {
                var ancestors = closures.AncestorClosures[node.Id];
                var descendants = closures.DescendantClosures[node.Id];
                results = new HashSet<int>(ancestors.Union(descendants).Union(results));
            }
            return BreadthFirstDeletion(startNode, results, includedNodes.ToArray());
            return null;
        }