source: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/NeedlemanWunsch.java @ 1733

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

Used Eclipse code cleanup

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