source: branches/nameserver/GDE/MUSCLE/src/difftreese.cpp

Last change on this file was 10390, checked in by aboeckma, 12 years ago

added muscle sourcles amd makefile

File size: 7.1 KB
Line 
1#include "muscle.h"
2#include "tree.h"
3
4#define TRACE   0
5
6/***
7Algorithm to compare two trees, X and Y.
8
9A node x in X and node y in Y are defined to be
10similar iff the set of leaves in the subtree under
11x is identical to the set of leaves under y.
12
13A node is defined to be changed iff it is not
14similar to any node in the other tree.
15
16Nodes x and y are defined to be married iff every
17node in the subtree under x is similar to a node
18in the subtree under y. Married nodes are considered
19to be equal. The subtrees under two married nodes can
20at most differ by exchanges of left and right branches,
21which we do not consider to be significant here.
22
23A node is changed iff it is not married. If a node is
24changed, then it has a dissimilar node in its subtree,
25and it follows immediately from the definition of marriage
26that its parent is also a bachelor. Hence all nodes on the
27path from a changed node to the root are changed.
28
29We assume the trees have the same set of leaves, so
30every leaf is trivially both similar and married to
31the same leaf in the opposite tree. Changed nodes
32are therefore always internal (i.e., non-leaf) nodes.
33
34Example:
35
36              -----A
37        -----k
38   ----j      -----B
39--i     -----C
40   ------D
41
42
43              -----A
44        -----p
45   ----n      -----B
46--m     -----D
47   ------C
48
49
50The following pairs of internal nodes are similar.
51
52        Nodes   Set of leaves
53        -----   -------------
54        k,p             A,B
55        i,m             A,B,C,D
56
57Changed nodes in the first tree are i and j, changed nodes
58in the second tree are m and n.
59
60Node k and p are married, but i and m are not (because j
61and n are changed). The diffs are C, D and k.
62
63To achieve O(N) we avoid traversing a given subtree multiple
64times and also avoid comparing lists of leaves.
65
66We visit nodes in depth-first order (i.e., a node is visited
67before its parent).
68
69If either child of a node is changed, we flag it as changed.
70
71If both children of the node we are visiting are married,
72we check whether the spouses of those children have the
73same parent in the other tree. If the parents are different,
74the current node is a bachelor. If they have the same parent,
75then the node we are visiting is the spouse of that parent.
76We assign this newly identified married couple a unique integer
77id. The id of a node is in one-to-one correspondence with the
78set of leaves in its subtree. Two nodes have the same set of
79leaves iff they have the same id. Changed nodes do not get
80an id.
81***/
82
83void DiffTreesE(const Tree &NewTree, const Tree &OldTree,
84  unsigned NewNodeIndexToOldNodeIndex[])
85        {
86#if     TRACE
87        Log("DiffTreesE NewTree:\n");
88        NewTree.LogMe();
89        Log("\n");
90        Log("OldTree:\n");
91        OldTree.LogMe();
92#endif
93
94        if (!NewTree.IsRooted() || !OldTree.IsRooted())
95                Quit("DiffTrees: requires rooted trees");
96
97        const unsigned uNodeCount = NewTree.GetNodeCount();
98        const unsigned uOldNodeCount = OldTree.GetNodeCount();
99        const unsigned uLeafCount = NewTree.GetLeafCount();
100        const unsigned uOldLeafCount = OldTree.GetLeafCount();
101        if (uNodeCount != uOldNodeCount || uLeafCount != uOldLeafCount)
102                Quit("DiffTreesE: different node counts");
103
104        {
105        unsigned *IdToOldNodeIndex = new unsigned[uNodeCount];
106        for (unsigned uOldNodeIndex = 0; uOldNodeIndex < uNodeCount; ++uOldNodeIndex)
107                {
108                if (OldTree.IsLeaf(uOldNodeIndex))
109                        {
110                        unsigned Id = OldTree.GetLeafId(uOldNodeIndex);
111                        IdToOldNodeIndex[Id] = uOldNodeIndex;
112                        }
113                }
114
115// Initialize NewNodeIndexToOldNodeIndex[]
116// All internal nodes are marked as changed, but may be updated later.
117        for (unsigned uNewNodeIndex = 0; uNewNodeIndex < uNodeCount; ++uNewNodeIndex)
118                {
119                if (NewTree.IsLeaf(uNewNodeIndex))
120                        {
121                        unsigned uId = NewTree.GetLeafId(uNewNodeIndex);
122                        assert(uId < uLeafCount);
123
124                        unsigned uOldNodeIndex = IdToOldNodeIndex[uId];
125                        assert(uOldNodeIndex < uNodeCount);
126
127                        NewNodeIndexToOldNodeIndex[uNewNodeIndex] = uOldNodeIndex;
128                        }
129                else
130                        NewNodeIndexToOldNodeIndex[uNewNodeIndex] = NODE_CHANGED;
131                }
132        delete[] IdToOldNodeIndex;
133        }
134
135// Depth-first traversal of tree.
136// The order guarantees that a node is visited before
137// its parent is visited.
138        for (unsigned uNewNodeIndex = NewTree.FirstDepthFirstNode();
139          NULL_NEIGHBOR != uNewNodeIndex;
140          uNewNodeIndex = NewTree.NextDepthFirstNode(uNewNodeIndex))
141                {
142                if (NewTree.IsLeaf(uNewNodeIndex))
143                        continue;
144
145        // If either child is changed, flag this node as changed and continue.
146                unsigned uNewLeft = NewTree.GetLeft(uNewNodeIndex);
147                unsigned uOldLeft = NewNodeIndexToOldNodeIndex[uNewLeft];
148                if (NODE_CHANGED == uOldLeft)
149                        {
150                        NewNodeIndexToOldNodeIndex[uNewLeft] = NODE_CHANGED;
151                        continue;
152                        }
153
154                unsigned uNewRight = NewTree.GetRight(uNewNodeIndex);
155                unsigned uOldRight = NewNodeIndexToOldNodeIndex[uNewRight];
156                if (NODE_CHANGED == NewNodeIndexToOldNodeIndex[uNewRight])
157                        {
158                        NewNodeIndexToOldNodeIndex[uNewRight] = NODE_CHANGED;
159                        continue;
160                        }
161
162                unsigned uOldParentLeft = OldTree.GetParent(uOldLeft);
163                unsigned uOldParentRight = OldTree.GetParent(uOldRight);
164                if (uOldParentLeft == uOldParentRight)
165                        NewNodeIndexToOldNodeIndex[uNewNodeIndex] = uOldParentLeft;
166                else
167                        NewNodeIndexToOldNodeIndex[uNewNodeIndex] = NODE_CHANGED;
168                }
169
170#if TRACE
171        {
172        Log("NewToOld ");
173        for (unsigned uNewNodeIndex = 0; uNewNodeIndex < uNodeCount; ++uNewNodeIndex)
174                {
175                Log(" [%3u]=", uNewNodeIndex);
176                if (NODE_CHANGED == NewNodeIndexToOldNodeIndex[uNewNodeIndex])
177                        Log("  X");
178                else
179                        Log("%3u", NewNodeIndexToOldNodeIndex[uNewNodeIndex]);
180                if ((uNewNodeIndex+1)%8 == 0)
181                        Log("\n         ");
182                }
183        Log("\n");
184        }
185#endif
186
187#if     DEBUG
188        {
189        for (unsigned uNewNodeIndex = 0; uNewNodeIndex < uNodeCount; ++uNewNodeIndex)
190                {
191                unsigned uOld = NewNodeIndexToOldNodeIndex[uNewNodeIndex];
192                if (NewTree.IsLeaf(uNewNodeIndex))
193                        {
194                        if (uOld >= uNodeCount)
195                                {
196                                Log("NewNode=%u uOld=%u > uNodeCount=%u\n",
197                                  uNewNodeIndex, uOld, uNodeCount);
198                                Quit("Diff check failed");
199                                }
200                        unsigned uIdNew = NewTree.GetLeafId(uNewNodeIndex);
201                        unsigned uIdOld = OldTree.GetLeafId(uOld);
202                        if (uIdNew != uIdOld)
203                                {
204                                Log("NewNode=%u uOld=%u IdNew=%u IdOld=%u\n",
205                                  uNewNodeIndex, uOld, uIdNew, uIdOld);
206                                Quit("Diff check failed");
207                                }
208                        continue;
209                        }
210
211                if (NODE_CHANGED == uOld)
212                        continue;
213
214                unsigned uNewLeft = NewTree.GetLeft(uNewNodeIndex);
215                unsigned uNewRight = NewTree.GetRight(uNewNodeIndex);
216
217                unsigned uOldLeft = OldTree.GetLeft(uOld);
218                unsigned uOldRight = OldTree.GetRight(uOld);
219
220                unsigned uNewLeftPartner = NewNodeIndexToOldNodeIndex[uNewLeft];
221                unsigned uNewRightPartner = NewNodeIndexToOldNodeIndex[uNewRight];
222
223                bool bSameNotRotated = (uNewLeftPartner == uOldLeft && uNewRightPartner == uOldRight);
224                bool bSameRotated = (uNewLeftPartner == uOldRight && uNewRightPartner == uOldLeft);
225                if (!bSameNotRotated && !bSameRotated)
226                        {
227                        Log("NewNode=%u NewL=%u NewR=%u\n", uNewNodeIndex, uNewLeft, uNewRight);
228                        Log("OldNode=%u OldL=%u OldR=%u\n", uOld, uOldLeft, uOldRight);
229                        Log("NewLPartner=%u NewRPartner=%u\n", uNewLeftPartner, uNewRightPartner);
230                        Quit("Diff check failed");
231                        }
232                }
233        }
234#endif
235        }
Note: See TracBrowser for help on using the repository browser.