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

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

Trying new approach

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