source: branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/pal/tree/NeighborJoiningTree.java @ 1573

Last change on this file since 1573 was 1573, checked in by rkrimmel, 10 years ago

Now really adding PAL Library

File size: 3.8 KB
Line 
1// NeighborJoiningTree.java
2//
3// (c) 1999-2001 PAL Development Core Team
4//
5// This package may be distributed under the
6// terms of the Lesser GNU General Public License (LGPL)
7
8
9// computational complexity O(numSeqs^3)
10
11
12package de.ugoe.cs.autoquest.tasktrees.alignment.pal.tree;
13
14import de.ugoe.cs.autoquest.tasktrees.alignment.matrix.UPGMAMatrix;
15
16
17/**
18 * constructs a neighbor-joining tree from pairwise distances
19 *
20 * @version $Id: NeighborJoiningTree.java,v 1.9 2001/07/13 14:39:13 korbinian Exp $
21 *
22 * @author Korbinian Strimmer
23 * @author Alexei Drummond
24 */
25public class NeighborJoiningTree extends SimpleTree
26{
27        //
28        // Public stuff
29        //     
30
31        /**
32         * construct NJ tree
33         *
34         * @param m distance matrix
35         */
36        public NeighborJoiningTree(UPGMAMatrix m)
37        {
38                if (m.size() < 3)
39                {
40                        new IllegalArgumentException("LESS THAN 3 TAXA IN DISTANCE MATRIX");
41                }
42                               
43                init(m);
44
45                //while (numClusters > 3)
46                while (true)
47                {
48                        findNextPair();
49                        newBranchLengths();
50                        if (numClusters == 3)
51                        {
52                                break;
53                        }
54                        newCluster();
55                }
56               
57                finish();
58        }
59
60
61        //
62        // Private stuff
63        //
64       
65        private int numClusters;
66        private Node newCluster;
67        private int besti, abi;
68        private int bestj, abj;
69        private int[] alias;
70        private double[][] distance;
71        private double[] r;
72        private double scale;   
73
74        private double getDist(int a, int b)
75        {
76                return distance[alias[a]][alias[b]];
77        }
78       
79        private void init(UPGMAMatrix m)
80        {
81                numClusters = m.size();
82
83                distance = new double[numClusters][numClusters];
84                for (int i = 0; i < numClusters; i++)
85                {
86                        for (int j = 0; j < numClusters; j++)
87                        {
88                                distance[i][j] = m.get(i,j);
89                        }
90                }
91
92                for (int i = 0; i < numClusters; i++)
93                {
94                        Node tmp = NodeFactory.createNode();
95                        //tmp.setIdentifier(m.getIdentifier(i));
96                        getRoot().addChild(tmp);
97                }
98               
99                alias = new int[numClusters];
100                for (int i = 0; i < numClusters; i++)
101                {
102                        alias[i] = i;
103                }
104               
105                r = new double[numClusters];
106        }
107
108        private void finish()
109        {
110                if (besti != 0 && bestj != 0)
111                {
112                        getRoot().getChild(0).setBranchLength(updatedDistance(besti, bestj, 0));
113                }
114                else if (besti != 1 && bestj != 1)
115                {
116                        getRoot().getChild(1).setBranchLength(updatedDistance(besti, bestj, 1));
117                }
118                else
119                {
120                        getRoot().getChild(2).setBranchLength(updatedDistance(besti, bestj, 2));
121                }
122                distance = null;
123
124                // make node heights available also
125                NodeUtils.lengths2Heights(getRoot());
126        }
127
128        private void findNextPair()
129        {
130                for (int i = 0; i < numClusters; i++)
131                {
132                        r[i] = 0;
133                        for (int j = 0; j < numClusters; j++)
134                        {
135                                r[i] += getDist(i,j);
136                        }
137                }
138
139                besti = 0;
140                bestj = 1;
141                double smax = -1.0;
142                scale = 1.0/(numClusters-2);
143                for (int i = 0; i < numClusters-1; i++)
144                {
145                        for (int j = i+1; j < numClusters; j++)
146                        {
147                                double sij = (r[i] + r[j] ) * scale - getDist(i, j);
148                       
149                                if (sij > smax)
150                                {
151                                        smax = sij;
152                                        besti = i;
153                                        bestj = j;
154                                }
155                        }
156                }
157                abi = alias[besti];
158                abj = alias[bestj];
159        }
160
161        private void newBranchLengths()
162        {
163                double dij = getDist(besti, bestj);
164                double li = (dij + (r[besti]-r[bestj])*scale)*0.5;
165                double lj = dij - li; // = (dij + (r[bestj]-r[besti])*scale)*0.5
166
167                getRoot().getChild(besti).setBranchLength(li);
168                getRoot().getChild(bestj).setBranchLength(lj);
169        }
170
171        private void newCluster()
172        {
173                // Update distances
174                for (int k = 0; k < numClusters; k++)
175                {
176                        if (k != besti && k != bestj)
177                        {
178                                int ak = alias[k];     
179                                distance[ak][abi] = distance[abi][ak] = updatedDistance(besti, bestj, k);
180                        }
181                }
182                distance[abi][abi] = 0.0;
183               
184                // Replace besti with new cluster
185                getRoot().joinChildren(besti, bestj);
186               
187                // Update alias
188                for (int i = bestj; i < numClusters-1; i++)
189                {
190                        alias[i] = alias[i+1];
191                }
192               
193                numClusters--;
194        }
195       
196        /**
197         * compute updated distance between the new cluster (i,j)
198         * to any other cluster k
199         */
200        private double updatedDistance(int i, int j, int k)
201        {
202                return (getDist(k, i) + getDist(k, j) - getDist(i, j))*0.5;
203        }
204}
Note: See TracBrowser for help on using the repository browser.