source: branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/NeedlemanWunsch.java @ 1612

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

Removed parameters from alignmentalgorihm factory constructor and changed interface by adding a new align() method, which now gets all the data via parameter

File size: 7.2 KB
Line 
1package de.ugoe.cs.autoquest.tasktrees.alignment.algorithms;
2
3import java.util.ArrayList;
4import java.util.Iterator;
5import java.util.LinkedList;
6
7import de.ugoe.cs.autoquest.tasktrees.alignment.matrix.SubstitutionMatrix;
8import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.Constants;
9
10
11public class NeedlemanWunsch implements AlignmentAlgorithm {
12
13        /**
14         * The first input
15         */
16        private int[] input1;
17
18        /**
19         * The second input String
20         */
21        private int[] input2;
22
23        /**
24         * The lengths of the input
25         */
26        private int length1, length2;
27
28        /**
29         * The score matrix. The true scores should be divided by the normalization
30         * factor.
31         */
32        private MatrixEntry[][] matrix;
33
34        private ArrayList<NumberSequence> alignment;
35
36        /**
37         * Substitution matrix to calculate scores
38         */
39        private SubstitutionMatrix submat;
40
41
42        /**
43         * Compute the similarity score of substitution The position of the first
44         * character is 1. A position of 0 represents a gap.
45         *
46         * @param i
47         *            Position of the character in str1
48         * @param j
49         *            Position of the character in str2
50         * @return Cost of substitution of the character in str1 by the one in str2
51         */
52        private double similarity(int i, int j) {
53                return submat.getScore(input1[i - 1], input2[j - 1]);
54        }
55
56        /**
57         * Build the score matrix using dynamic programming.
58         */
59        private void buildMatrix() {
60                if (submat.getGapPenalty() >= 0) {
61                        throw new Error("Indel score must be negative");
62                }
63
64                // it's a gap
65                matrix[0][0].setScore(0);
66                matrix[0][0].setPrevious(null); // starting point
67
68                // the first column
69                for (int j = 1; j <= length2; j++) {
70                        matrix[0][j].setScore(j*submat.getGapPenalty());
71                        matrix[0][j].setPrevious(matrix[0][j - 1]);
72                        matrix[0][j].setYvalue(input2[j-1]);
73                        matrix[0][j].setXvalue(Constants.GAP_SYMBOL);
74                }
75                // the first row
76
77                for (int j = 1; j <= length1; j++) {
78                        matrix[j][0].setScore(j*submat.getGapPenalty());
79                        matrix[j][0].setPrevious(matrix[j - 1][0]);
80                        matrix[j][0].setXvalue(input1[j-1]);
81                        matrix[j][0].setYvalue(Constants.GAP_SYMBOL);
82                }
83
84                for (int i = 1; i <= length1; i++) {
85
86                        for (int j = 1; j <= length2; j++) {
87                                double diagScore = matrix[i - 1][j - 1].getScore()
88                                                + similarity(i, j);
89                                double upScore = matrix[i][j - 1].getScore()
90                                                + submat.getGapPenalty();
91                                double leftScore = matrix[i - 1][j].getScore()
92                                                + submat.getGapPenalty();
93
94                                matrix[i][j].setScore(Math.max(diagScore,
95                                                Math.max(upScore, leftScore)));
96
97                                // find the directions that give the maximum scores.
98                                // TODO: Multiple directions are ignored, we choose the first
99                                // maximum score
100                                // True if we had a match
101                                if (diagScore == matrix[i][j].getScore()) {
102                                        matrix[i][j].setPrevious(matrix[i - 1][j - 1]);
103                                        matrix[i][j].setXvalue(input1[i - 1]);
104                                        matrix[i][j].setYvalue(input2[j - 1]);
105                                }
106                                // true if we took an event from sequence x and not from y
107                                if (leftScore == matrix[i][j].getScore()) {
108                                        matrix[i][j].setXvalue(input1[i - 1]);
109                                        matrix[i][j].setYvalue(Constants.GAP_SYMBOL);
110                                        matrix[i][j].setPrevious(matrix[i - 1][j]);
111                                }
112                                // true if we took an event from sequence y and not from x
113                                if (upScore == matrix[i][j].getScore()) {
114                                        matrix[i][j].setXvalue(Constants.GAP_SYMBOL);
115                                        matrix[i][j].setYvalue(input2[j - 1]);
116                                        matrix[i][j].setPrevious(matrix[i][j - 1]);
117                                }
118                        }
119                }
120        }
121
122        /**
123         * Get the maximum value in the score matrix.
124         */
125        public double getMaxScore() {
126                double maxScore = 0;
127
128                // skip the first row and column
129                for (int i = 1; i <= length1; i++) {
130                        for (int j = 1; j <= length2; j++) {
131                                if (matrix[i][j].getScore() > maxScore) {
132                                        maxScore = matrix[i][j].getScore();
133                                }
134                        }
135                }
136
137                return maxScore;
138        }
139
140        /*
141         * (non-Javadoc)
142         *
143         * @see
144         * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm
145         * #getAlignmentScore()
146         */
147        @Override
148        public double getAlignmentScore() {
149                return getMaxScore();
150        }
151
152        public void traceback() {
153                MatrixEntry tmp = matrix[length1][length2];
154                LinkedList<Integer> aligned1 = new LinkedList<Integer>();
155                LinkedList<Integer> aligned2 = new LinkedList<Integer>();
156                do {
157                       
158                        aligned1.add(new Integer(tmp.getXvalue()));
159                        aligned2.add(new Integer(tmp.getYvalue()));
160
161                        tmp = tmp.getPrevious();
162
163                } while (tmp != null);
164               
165                // reverse order of the alignment
166                int reversed1[] = new int[aligned1.size()];
167                int reversed2[] = new int[aligned2.size()];
168
169                int count = 0;
170                for (Iterator<Integer> it = aligned1.descendingIterator(); it.hasNext();) {
171                        count++;
172                        reversed1[reversed1.length - count] = it.next();
173                       
174                }
175                count = 0;
176                for (Iterator<Integer> it = aligned2.descendingIterator(); it.hasNext();) {
177                        count++;
178                        reversed2[reversed2.length - count] = it.next();
179                }
180
181                NumberSequence ns1 = new NumberSequence(reversed1.length);
182                NumberSequence ns2 = new NumberSequence(reversed2.length);
183                ns1.setSequence(reversed1);
184                ns2.setSequence(reversed2);
185
186                alignment.add(ns1);
187                alignment.add(ns2);
188        }
189
190        public void printAlignment() {
191                MatrixEntry tmp = matrix[length1][length2];
192                String aligned1 = "";
193                String aligned2 = "";
194                int count = 0;
195                do {
196                        System.out.println(tmp);
197                        String append1 = "";
198                        String append2 = "";
199
200                        if (tmp.getXvalue() == Constants.GAP_SYMBOL) {
201                                append1 = "  ___";
202                        } else {
203                                append1 = String.format("%5d", tmp.getXvalue());
204                        }
205
206                        if (tmp.getYvalue() == Constants.GAP_SYMBOL) {
207                                append2 = "  ___";
208                        } else {
209                                append2 = String.format("%5d", tmp.getYvalue());
210                        }
211                        if (count != 0) {
212                                aligned1 = append1 + aligned1;
213                                aligned2 = append2 + aligned2;
214                        }
215
216                        tmp = tmp.getPrevious();
217                        count++;
218
219                } while (tmp != null);
220                System.out.println(aligned1);
221                System.out.println(aligned2);
222        }
223
224        /**
225         * print the dynmaic programming matrix
226         */
227        public void printDPMatrix() {
228                System.out.print("          ");
229                for (int i = 1; i <= length1; i++)
230                        System.out.format("%5d", input1[i - 1]);
231                System.out.println();
232                for (int j = 0; j <= length2; j++) {
233                        if (j > 0)
234                                System.out.format("%5d ", input2[j - 1]);
235                        else {
236                                System.out.print("      ");
237                        }
238                        for (int i = 0; i <= length1; i++) {
239                                        System.out.format("%4.1f ", matrix[i][j].getScore());
240                        }
241                        System.out.println();
242                }
243        }
244
245        /*
246         * (non-Javadoc)
247         *
248         * @see
249         * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm
250         * #getAlignment()
251         */
252        @Override
253        public ArrayList<NumberSequence> getAlignment() {
254                return alignment;
255        }
256
257        public void setAlignment(ArrayList<NumberSequence> alignment) {
258                this.alignment = alignment;
259        }
260
261        @Override
262        public ArrayList<ArrayList<NumberSequence>> getMatches() {
263                // TODO Auto-generated method stub
264                return null;
265        }
266
267        @Override
268        public void align(int[] input1, int[] input2, SubstitutionMatrix submat,
269                        float threshold) {
270                this.input1 = input1;
271                this.input2 = input2;
272                length1 = input1.length;
273                length2 = input2.length;
274                this.submat = submat;
275
276                // System.out.println("Starting SmithWaterman algorithm with a "
277                // + submat.getClass() + " Substitution Matrix: " +
278                // submat.getClass().getCanonicalName());
279
280                matrix = new MatrixEntry[length1 + 1][length2 + 1];
281                alignment = new ArrayList<NumberSequence>();
282
283                for (int i = 0; i < length1+1; i++) {
284                        for (int j = 0; j < length2+1; j++) {
285                                matrix[i][j] = new MatrixEntry();
286                        }
287                }
288
289                buildMatrix();
290                traceback();
291               
292        }
293
294
295
296}
Note: See TracBrowser for help on using the repository browser.