Esempio n. 1
0
        /// <inheritdoc />
        public override int Similarity(ITreeNode <T> other, DEquality <ITreeNode <T> > equality)
        {
            int similarity = equality(this, other) ? 1 : 0;

            List <ITreeNode <T> > nodes = new List <ITreeNode <T> >(other.Children);

            foreach (ITreeNode <T> child in Children)
            {
                ITreeNode <T> node = nodes.Find(n => equality(n, child));

                // if node is default then no equal node exists. subtract from similarity
                if (node == default(ITreeNode <T>))
                {
                    similarity -= (1 + child.DescendentCount);
                }
                // Otherwise, add the similarity of the new node
                else
                {
                    similarity += child.Similarity(node);
                    nodes.Remove(node);
                }
            }

            // subtract remaining
            foreach (ITreeNode <T> child in nodes)
            {
                similarity -= (1 + child.DescendentCount);
            }

            return(similarity);
        }
Esempio n. 2
0
        /// <inheritdoc />
        public override ITreeNode <T> Difference(ITreeNode <T> other, DEquality <ITreeNode <T> > traversalEquality, DEquality <T> deletionEquality)
        {
            // if nodes arn't equal return nothing
            if (Equals(other))
            {
                return(null);
            }

            // if these arn't traversal equal, return a copy of this node
            if (!traversalEquality(this, other))
            {
                return(Copy());
            }

            // if this has no children, test for deletion
            if (ChildCount == 0)
            {
                return(deletionEquality(Value, other.Value) ? null : new UniqueChildrenTreeNode <T>(this.Value));
            }

            // if other has no children, retun this as copy
            if (other.ChildCount == 0)
            {
                return(Copy());
            }

            // calculate difference of children nodes
            UniqueChildrenTreeNode <T> differenceTree = new UniqueChildrenTreeNode <T>(Value);

            List <ITreeNode <T> > originalNodesWithoutTraversalNeighbour = new List <ITreeNode <T> >(Children);

            foreach (ITreeNode <T> child in other.Children)
            {
                ITreeNode <T> traversalNode = originalNodesWithoutTraversalNeighbour.Find(n => traversalEquality(n, child));

                // if node exists, perform a difference and add new node to output
                if (traversalNode != default(ITreeNode <T>))
                {
                    UniqueChildrenTreeNode <T> newDifference
                        = traversalNode.Difference(child, traversalEquality, deletionEquality) as UniqueChildrenTreeNode <T>;

                    originalNodesWithoutTraversalNeighbour.Remove(traversalNode);

                    if (newDifference == null)
                    {
                        continue;
                    }

                    UnsafeAddChild(differenceTree, newDifference);
                }
            }

            // Add all nodes without a traversale neighbour to output
            foreach (ITreeNode <T> node in originalNodesWithoutTraversalNeighbour)
            {
                node.Copy(differenceTree);
            }

            return(differenceTree);
        }
Esempio n. 3
0
        /// <inheritdoc />
        public override ITreeNode <T> Union(ITreeNode <T> other, DEquality <ITreeNode <T> > equality, DMerge <T> merge)
        {
            // if there not equal, Union results in null
            if (!equality(this, other))
            {
                return(null);
            }

            // Create a new node using the provided merge rule.
            // The merge rule determines how equal values resolve
            TreeNode <T> unionTree = new TreeNode <T>(merge(Value, other.Value));

            // Get the children of the other node, to test against the children of the current node
            List <ITreeNode <T> > testNodes = new List <ITreeNode <T> >(other.Children);

            // Foreach node in Children, preform a test to determine the case and handle
            // the union calculation
            foreach (ITreeNode <T> child in Children)
            {
                // candidates for a deeper union are testsNodes that equal the child
                IEnumerable <ITreeNode <T> > candidates = testNodes.Where(n => equality(n, child));

                // if no candidates, add this child to the new tree
                if (candidates == null || candidates.Count() == 0)
                {
                    child.Copy(unionTree);
                    continue;
                }

                // Determine which candidate should be used to perform the union
                // This is the most similar candidate
                ITreeNode <T> chosenCandidate = null;

                if (candidates.Count() == 1)
                {
                    chosenCandidate = candidates.First();
                }
                else
                {
                    chosenCandidate = child.MostSimilar(candidates);
                }

                // Perform a union with the chosen candidate
                InternalAddChild(unionTree, child.Union(chosenCandidate, equality, merge) as TreeNode <T>);

                // Remove the candidate
                testNodes.Remove(chosenCandidate);
            }

            // Add all remaining nodes without performing a merge
            foreach (ITreeNode <T> node in testNodes)
            {
                node.Copy(unionTree);
            }

            return(unionTree);
        }
Esempio n. 4
0
        /// <inheritdoc />
        public override ITreeNode <T> Intersection(ITreeNode <T> other, DEquality <ITreeNode <T> > equality)
        {
            // return null if other is null or if this does not equal other
            if (other == null || !equality(this, other))
            {
                return(null);
            }

            // make a new node as the intersection tree
            TreeNode <T> intersectionTree = new TreeNode <T>(Value);

            // Get other children as nodes to test for intersection
            List <ITreeNode <T> > testNodes = new List <ITreeNode <T> >(other.Children);

            // Determine which candidate should be used to perform the intersection
            // This is the most similar candidate
            foreach (ITreeNode <T> child in Children)
            {
                // candidates are children that are equal
                IEnumerable <ITreeNode <T> > candidates = testNodes.Where(n => equality(n, child));

                // if there are no candidates, ignore this child. These are not included in the
                // intersection
                if (candidates == null || candidates.Count() == 0)
                {
                    continue;
                }

                // chose the mosre similar candidate available
                ITreeNode <T> chosenCandidate = null;

                if (candidates.Count() == 1)
                {
                    chosenCandidate = candidates.First();
                }
                else
                {
                    chosenCandidate = child.MostSimilar(candidates);
                }

                // Add the intersection of child and candidate and add the result to the tree
                InternalAddChild(intersectionTree, child.Intersection(chosenCandidate, equality) as TreeNode <T>);
                testNodes.Remove(chosenCandidate);
            }

            return(intersectionTree);
        }
Esempio n. 5
0
        /// <inheritdoc />
        public override ITreeNode <T> Intersection(ITreeNode <T> other, DEquality <ITreeNode <T> > equality)
        {
            // if not equal return null
            if (!equality(this, other))
            {
                return(null);
            }

            // if netiehr have children return new tree node
            if (ChildCount == 0 || other.ChildCount == 0)
            {
                return(new UniqueChildrenTreeNode <T>(Value));
            }

            // process node and children to find intersection
            UniqueChildrenTreeNode <T> intersectionRoot = new UniqueChildrenTreeNode <T>(Value);

            List <ITreeNode <T> > otherChildren = new List <ITreeNode <T> >(other.Children);

            foreach (ITreeNode <T> originalChild in Children)
            {
                ITreeNode <T> matchingOtherNode = otherChildren.Find(n => equality(n, originalChild));

                // if a match exists, perform an intersection
                if (matchingOtherNode != default(ITreeNode <T>))
                {
                    UniqueChildrenTreeNode <T> newIntersection
                        = originalChild.Intersection(matchingOtherNode) as UniqueChildrenTreeNode <T>;

                    if (newIntersection == null)
                    {
                        continue;
                    }

                    UnsafeAddChild(intersectionRoot, newIntersection);
                    otherChildren.Remove(matchingOtherNode);
                }
            }
            return(intersectionRoot);
        }
Esempio n. 6
0
 /// <inheritdoc />
 public abstract ITreeNode <T> Union(ITreeNode <T> other, DEquality <ITreeNode <T> > equality, DMerge <T> merge);
Esempio n. 7
0
 /// <inheritdoc />
 public abstract ITreeNode <T> Union(ITreeNode <T> other, DEquality <ITreeNode <T> > equality);
Esempio n. 8
0
 /// <inheritdoc />
 public abstract int Similarity(ITreeNode <T> other, DEquality <ITreeNode <T> > equality);
Esempio n. 9
0
 /// <inheritdoc />
 public abstract ITreeNode <T> Difference(ITreeNode <T> other, DEquality <ITreeNode <T> > traversal_equality, DEquality <T> deletion_equality);
Esempio n. 10
0
 /// <inheritdoc />
 public abstract ITreeNode <T> Intersection(ITreeNode <T> other, DEquality <ITreeNode <T> > equality);
Esempio n. 11
0
        /// <inheritdoc />
        public override int Similarity(ITreeNode <T> other, DEquality <ITreeNode <T> > equality)
        {
            // if equal, give one similarity point
            int similarity = equality(this, other) ? 1 : 0;

            // Find out how many children are similar
            int sharedChildren = UTIEquatable.SharedValuesCount <T>(
                Children.Select(n => n.Value), other.Children.Select(n => n.Value)
                );

            // remove similarity points based on non-shared children
            similarity -= (ChildCount - sharedChildren);
            similarity -= (other.ChildCount - sharedChildren);

            // Use other children as a test of similarity
            List <ITreeNode <T> > testNodes = new List <ITreeNode <T> >(other.Children);

            foreach (ITreeNode <T> child in Children)
            {
                // determine the pairedNode (Node that is the equivalent of the this node)
                ITreeNode <T> pairedNode = null;

                // Find the nodes that are considered equal
                IEnumerable <ITreeNode <T> > possibleTestNodes = testNodes.Where(n => equality(n, child));
                int count = possibleTestNodes.Count();

                if (count > 1)
                {
                    // if there is more than one possible test node, do a similarity test on each
                    // and set paired node to the most similar.
                    int innerSimilarity = int.MinValue;

                    foreach (ITreeNode <T> node in possibleTestNodes)
                    {
                        int sim = child.Similarity(node, equality);

                        if (sim > innerSimilarity)
                        {
                            innerSimilarity = sim;
                            pairedNode      = node;
                        }
                    }

                    // Add the innerSimilarity to the similarity calculation
                    similarity += innerSimilarity;
                }
                else if (count == 1)
                {
                    // if there is only one, then add the similarty of these nodes
                    // and remove the test node
                    ITreeNode <T> testNode = possibleTestNodes.First();
                    similarity += child.Similarity(testNode, equality);
                    pairedNode  = testNode;
                }

                // remove candidate
                if (pairedNode != null)
                {
                    testNodes.Remove(pairedNode);
                }
            }

            // All lingering nodes are subtracted from similarity
            foreach (ITreeNode <T> node in testNodes)
            {
                similarity -= node.DescendentCount;
            }

            return(similarity);
        }
Esempio n. 12
0
        /// <inheritdoc />
        public override ITreeNode <T> Difference(ITreeNode <T> other, DEquality <ITreeNode <T> > travsersalEquality, DEquality <T> deletionEquality)
        {
            // nodes do not meet traveseral criteria, no further difference can be performed and
            // the original node value is returned. Difference ends here
            if (!travsersalEquality(this, other))
            {
                return(new TreeNode <T>(Value));
            }

            // If there are no more children that could be removed, check if the node should be deleted.
            // if so delete, otherwise, keep
            if (ChildCount == 0)
            {
                return(deletionEquality(Value, other.Value) ? null : new TreeNode <T>(Value));
            }

            // Make a tree with the current value
            TreeNode <T> differenceTree = new TreeNode <T>(Value);

            // test against the childrne of the other
            List <ITreeNode <T> > testNodes = new List <ITreeNode <T> >(other.Children);

            foreach (ITreeNode <T> child in Children)
            {
                // candidates for travseral match travseralEquality
                IEnumerable <ITreeNode <T> > candidates = testNodes.Where(n => travsersalEquality(n, child));

                // if there are no candidates, then copy this child to the difference tree
                // it is kept, and not deleted
                if (candidates == null || candidates.Count() == 0)
                {
                    child.Copy(differenceTree);
                    continue;
                }

                // find the candidate that requires traversal for more granular difference
                // This is the most similar node
                ITreeNode <T> chosenCandidate = null;

                if (candidates.Count() == 1)
                {
                    chosenCandidate = candidates.First();
                }
                else
                {
                    chosenCandidate = child.MostSimilar(candidates);
                }

                // Perform a difference on the current child and the chosen candidate
                TreeNode <T> possibleChild = child.Difference(chosenCandidate, travsersalEquality, deletionEquality) as TreeNode <T>;

                // If the child isn't null, add it to the difference tree
                if (possibleChild != null)
                {
                    InternalAddChild(differenceTree, possibleChild);
                }

                // remove candidate from future tests
                testNodes.Remove(chosenCandidate);
            }

            // if there are no children in the difference tree,  check if it should be deleted
            if (differenceTree.ChildCount == 0)
            {
                return(deletionEquality(Value, other.Value) ? null : new TreeNode <T>(Value));
            }

            return(differenceTree);
        }
Esempio n. 13
0
 /// <inheritdoc />
 public override ITreeNode <T> Difference(ITreeNode <T> other, DEquality <ITreeNode <T> > travsersalEquality)
 {
     return(Difference(other, travsersalEquality, (t1, t2) => true));
 }
Esempio n. 14
0
 /// <inheritdoc />
 public override ITreeNode <T> Union(ITreeNode <T> other, DEquality <ITreeNode <T> > equality)
 {
     return(Union(other, equality, (o1, o2) => o1));
 }
Esempio n. 15
0
        /// <inheritdoc />
        public override ITreeNode <T> Union(ITreeNode <T> other, DEquality <ITreeNode <T> > equality, DMerge <T> merge)
        {
            // if not equal, return null
            if (!equality(this, other))
            {
                return(null);
            }

            // since values are equal, if they both have no children, return node with value
            if (ChildCount == 0 && other.ChildCount == 0)
            {
                return(new UniqueChildrenTreeNode <T>(merge(Value, other.Value)));
            }

            // return copy of node with children if only 1 has children
            if (ChildCount > 0 && other.ChildCount == 0)
            {
                return(Copy());
            }

            if (other.ChildCount > 0 && ChildCount == 0)
            {
                return(other.Copy());
            }

            // set up the union tree for recursive calculation
            UniqueChildrenTreeNode <T> unionTree = new UniqueChildrenTreeNode <T>(merge(Value, other.Value));

            // sort out children in both that have no equivalent in other
            // perform a union on any nodes that match
            List <ITreeNode <T> > otherNodesNotInOriginal = new List <ITreeNode <T> >(other.Children);
            List <ITreeNode <T> > originalNodesNotInOther = new List <ITreeNode <T> >();

            foreach (ITreeNode <T> child in Children)
            {
                ITreeNode <T> matchingOtherNode = otherNodesNotInOriginal.Find(n => equality(n, child));

                if (matchingOtherNode == default(ITreeNode <T>))
                {
                    originalNodesNotInOther.Add(child);
                }
                else
                {
                    UniqueChildrenTreeNode <T> newUnion
                        = child.Union(matchingOtherNode) as UniqueChildrenTreeNode <T>;

                    if (newUnion == null)
                    {
                        continue;
                    }

                    // add union of matching nodes to tree
                    UnsafeAddChild(unionTree, newUnion);
                    otherNodesNotInOriginal.Remove(matchingOtherNode);
                }
            }

            // copy other nodes missing from original
            foreach (ITreeNode <T> node in otherNodesNotInOriginal)
            {
                node.Copy(unionTree);
            }

            // copy original nodes missing from other
            foreach (ITreeNode <T> node in originalNodesNotInOther)
            {
                node.Copy(unionTree);
            }

            return(unionTree);
        }