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

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

Some refactoring for storing the initial alignments so we don't need to do them again.

File size: 4.5 KB
Line 
1// UPGMATree.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// Known bugs and limitations:
9// - computational complexity O(numSeqs^3)
10//   (this could be brought down to O(numSeqs^2)
11//   but this needs more clever programming ...)
12
13
14package de.ugoe.cs.autoquest.tasktrees.alignment.pal.tree;
15
16import java.util.ArrayList;
17
18import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.NumberSequence;
19import de.ugoe.cs.autoquest.tasktrees.alignment.matrix.BinaryAlignmentStorage;
20import de.ugoe.cs.autoquest.tasktrees.alignment.matrix.UPGMAMatrix;
21import de.ugoe.cs.autoquest.tasktrees.alignment.pal.misc.Identifier;
22
23
24/**
25 * constructs a UPGMA tree from pairwise distances
26 *
27 * @version $Id: UPGMATree.java,v 1.9 2001/07/13 14:39:13 korbinian Exp $
28 *
29 * @author Korbinian Strimmer
30 * @author Alexei Drummond
31 */
32public class UPGMAAligningTree extends SimpleTree
33{
34        //
35        // Public stuff
36        //     
37
38        /**
39         * constructor UPGMA tree
40         * @param numberseqs
41         *
42         * @param m distance matrix
43         */
44        public UPGMAAligningTree(ArrayList<NumberSequence> numberseqs, BinaryAlignmentStorage alignments)
45        {
46                if (alignments.getDistanceMatrix().size() < 2)
47                {
48                        new IllegalArgumentException("LESS THAN 2 TAXA IN DISTANCE MATRIX");
49                }
50       
51                this.numberseqs = numberseqs;
52                this.alignments = alignments;
53                init(alignments.getDistanceMatrix());
54
55                while (true)
56                {
57                        findNextPair();
58                        newBranchLengths();
59                       
60                        if (numClusters == 2)
61                        {
62                                break;
63                        }
64                       
65                        newCluster();
66                }
67               
68                finish();
69                createNodeList();
70        }
71
72
73        //
74        // Private stuff
75        //
76        private ArrayList<NumberSequence> numberseqs;
77        private BinaryAlignmentStorage alignments;
78        private int numClusters;
79        private int besti, abi;
80        private int bestj, abj;
81        private int[] alias;
82        private double[][] distance;
83
84        private double[] height;
85        private int[] oc;
86
87        private double getDist(int a, int b)
88        {
89                return distance[alias[a]][alias[b]];
90        }
91       
92        private void init(UPGMAMatrix m)
93        {
94                numClusters = m.size();
95
96                distance = new double[numClusters][numClusters];
97                for (int i = 0; i < numClusters; i++)
98                {
99                        for (int j = 0; j < numClusters; j++)
100                        {
101                                distance[i][j] = m.get(i,j);
102                        }
103                }
104
105                for (int i = 0; i < numClusters; i++)
106                {
107                        Node tmp = NodeFactory.createNode();
108                        tmp.setIdentifier(new Identifier(Integer.toString(i)));
109                        tmp.addSequence(numberseqs.get(i));
110                        getRoot().addChild(tmp);
111                }
112               
113                alias = new int[numClusters];
114                for (int i = 0; i < numClusters; i++)
115                {
116                        alias[i] = i;
117                }
118                               
119                height = new double[numClusters];
120                oc = new int[numClusters];
121                for (int i = 0; i < numClusters; i++)
122                {
123                        height[i] = 0.0;
124                        oc[i] = 1;
125                }
126        }
127
128        private void finish()
129        {
130                distance = null;               
131        }
132
133        private void findNextPair()
134        {
135                besti = 0;
136                bestj = 1;
137                double dmin = getDist(0, 1);
138                for (int i = 0; i < numClusters-1; i++)
139                {
140                        for (int j = i+1; j < numClusters; j++)
141                        {
142                                if (getDist(i, j) < dmin)
143                                {
144                                        dmin = getDist(i, j);
145                                        besti = i;
146                                        bestj = j;
147                                }
148                        }
149                }
150                abi = alias[besti];
151                abj = alias[bestj];
152                //System.out.println("Found best pair: " + abi + "/" +abj + " - "+ besti+ "/"+bestj +" with distance " + dmin);
153               
154        }
155
156        private void newBranchLengths()
157        {
158                double dij = getDist(besti, bestj);
159               
160                getRoot().getChild(besti).setBranchLength(dij/2.0-height[abi]);
161                getRoot().getChild(bestj).setBranchLength(dij/2.0-height[abj]);
162        }
163
164        private void newCluster()
165        {
166                // Update distances
167                for (int k = 0; k < numClusters; k++)
168                {
169                        if (k != besti && k != bestj)
170                        {
171                                int ak = alias[k];
172                                double updated = updatedDistance(besti,bestj,k);
173                                distance[ak][abi] = distance[abi][ak] = updated;
174                        }
175                }
176                distance[abi][abi] = 0.0;
177
178                // Update UPGMA variables
179                height[abi] = getDist(besti, bestj)/2.0;
180                oc[abi] += oc[abj];
181               
182                // Index besti now represent the new cluster
183                getRoot().joinChildren(besti, bestj);
184               
185                // Update alias
186                for (int i = bestj; i < numClusters-1; i++)
187                {
188                        alias[i] = alias[i+1];
189                }
190               
191                numClusters--;
192        }
193
194       
195        /**
196         * compute updated distance between the new cluster (i,j)
197         * to any other cluster k
198         */
199        private double updatedDistance(int i, int j, int k)
200        {
201                int ai = alias[i];
202                int aj = alias[j];
203               
204                double ocsum = (double) (oc[ai]+oc[aj]);
205                double idist = getDist(k,i);
206                double jdist = getDist(k,j);
207                //TODO: Dirty hack to deal with infinity, insert proper solution here
208                if(Double.isInfinite(idist)) {
209                        idist = 100;
210                }
211                if(Double.isInfinite(jdist)) {
212                        jdist = 100;
213                }
214               
215                return  (oc[ai]/ocsum)*idist+
216                        (oc[aj]/ocsum)*jdist;
217        }
218}
Note: See TracBrowser for help on using the repository browser.