DP-HLS
 All Classes Namespaces Files Functions Variables Typedefs Macros Pages
solutions.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <map>
4 #include <iostream>
5 #include <array>
6 #include <string>
7 #include <limits>
8 #include <fstream>
9 #include <iostream>
10 #include <iomanip> // For std::setw and std::setfill
11 #include <complex>
12 #include <set>
13 
14 using namespace std;
15 
16 namespace SolutionUtils
17 {
18  namespace Profile
19  {
20  template <int ALPHABET_SIZE>
21  float score_mult(const std::array<int, ALPHABET_SIZE> &query, const std::array<int, ALPHABET_SIZE> &reference,
22  const std::array<std::array<float, ALPHABET_SIZE>, ALPHABET_SIZE> &A)
23  {
24  float score = 0;
25  for (int i = 0; i < ALPHABET_SIZE; ++i)
26  {
27  for (int j = 0; j < ALPHABET_SIZE; ++j)
28  {
29  score += query[i] * A[i][j] * reference[j];
30  }
31  }
32  return score;
33  }
34  }
35 }
36 
37 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS>
38 void profile_alignment_solution(std::vector<std::array<int, 5>> query, std::vector<std::array<int, 5>> reference, PENALTY_T &penalties,
39  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
40  array<array<char, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
41  std::vector<char> &alignments)
42 {
43  // Function to calculate the score between two profile columns using the transition matrix A
44  const int ALPHABET_SIZE = 5; // A, T, C, G, _
45 
46  int query_len = query.size();
47  int reference_len = reference.size();
48 
49  // Create a score matrix
50  std::array<std::array<std::array<float, SOL_MAX_REFERENCE_LENGTH + 1>, SOL_MAX_QUERY_LENGTH + 1>, SOL_N_LAYERS> score_matrix;
51 
52  // Initialize the DP matrix, if necessary, e.g., for global alignment
53  // penalties has an entry of linear_gap. We initialize the gap for this alignment as in global alignment
54  score_matrix[0][0][0] = 0;
55  float accumulate = 0;
56  for (int i = 0; i < query_len; ++i)
57  {
58  accumulate += penalties.linear_gap;
59  score_matrix[0][i][0] = accumulate;
60  }
61  accumulate = 0;
62  for (int j = 0; j < reference_len; ++j)
63  {
64  accumulate += penalties.linear_gap;
65  score_matrix[0][0][j] = accumulate;
66  }
67 
68  // Fill in the DP matrix
69  for (int i = 1; i <= query_len; ++i)
70  {
71  for (int j = 1; j <= reference_len; ++j)
72  {
73  float intermidiate_score = SolutionUtils::Profile::score_mult<5>(query[i - 1], reference[j - 1], penalties.transition);
74  float matchScore = score_matrix[0][i - 1][j - 1] + intermidiate_score; // Match or mismatch
75  float deleteScore = score_matrix[0][i - 1][j] + intermidiate_score; // Or with a penalty
76  float insertScore = score_matrix[0][i][j - 1] + intermidiate_score; // Or with a penalty
77  score_matrix[0][i][j] = std::max(matchScore, std::max(deleteScore, insertScore)); // 0 for local alignment
78  // Set the traceback pointer
79  if (score_matrix[0][i][j] == matchScore)
80  {
81  tb_mat[i - 1][j - 1] = 'D'; // 'D' indicates a diagonal direction (match or mismatch)
82  }
83  else if (score_matrix[0][i][j] == deleteScore)
84  {
85  tb_mat[i - 1][j - 1] = 'U'; // 'U' indicates an up direction (deletion)
86  }
87  else
88  {
89  tb_mat[i - 1][j - 1] = 'L'; // 'L' indicates a left direction (insertion)
90  }
91  }
92  }
93 
94  // Copy the score matrix such that it have no initial values
95  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
96  {
97  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
98  {
99  score_mat[0][i][j] = score_matrix[0][i + 1][j + 1];
100  }
101  }
102 
103  // Trace-back to find the best alignment, starting from the maximum score in the DP matrix
104  // Implementation depends on the desired alignment type (global, local, etc.)
105  // Here, we implement a simple global alignment tracevack
106  int i = query.size() - 1;
107  int j = reference.size() - 1;
108  // Only reconstruct the traceback path, but don't print the alignment
109  while (i >= 0 && j >= 0)
110  {
111  if (tb_mat[i][j] == 'D')
112  {
113  i--;
114  j--;
115  alignments.push_back('D');
116  }
117  else if (tb_mat[i][j] == 'U')
118  {
119  i--;
120  alignments.push_back('U');
121  }
122  else if (tb_mat[i][j] == 'L')
123  {
124  j--;
125  alignments.push_back('L');
126  }
127  else
128  {
129  std::cout << "ERROR: Invalid traceback matrix value" << std::endl;
130  break;
131  }
132  }
133 
134  return;
135 }
136 
137 // >>> Global Linear Solution >>>
138 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS>
139 void global_linear_solution(std::string query, std::string reference, PENALTY_T &penalties,
140  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
141  array<array<char, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
142  map<string, string> &alignments)
143 {
144  // NOTE: we cannot augment the score matrix like this in the hardware since
145  // the initial scores for the following wavefronts will be shifted away in
146  // the dp_mem!
147 
148  // declare the intial column and row
149  array<float, SOL_MAX_QUERY_LENGTH> initial_col;
150  array<float, SOL_MAX_REFERENCE_LENGTH> initial_row;
151 
152  // initialize the initial column
153  float upper_left_value = 0;
154  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
155  {
156  upper_left_value += penalties.linear_gap; // since it was declared with type_t then convert back to int.
157  initial_col[i] = upper_left_value;
158  }
159 
160  // initialize the initial row
161  upper_left_value = 0; // FIXME: This might to be initialized as 0
162  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
163  {
164  upper_left_value += penalties.linear_gap; // since it was declared with type_t then convert back to int.
165  initial_row[j] = upper_left_value;
166  }
167 
168  // initialize the score_matrix
169  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
170  {
171  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
172  {
173  score_mat[0][i][j] = 0;
174  }
175  }
176 
177  // initialize the traceback matrix
178  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
179  {
180  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
181  {
182  tb_mat[i][j] = '*';
183  }
184  }
185 
186  // Fill in the DP matrix and traceback matrix
187  for (int i = 0; i < query.length(); i++)
188  {
189  int scr_diag, scr_up, scr_left;
190  for (int j = 0; j < reference.length(); j++)
191  {
192  if (i == 0 && j == 0)
193  {
194  scr_diag = 0;
195  scr_up = initial_row[j];
196  scr_left = initial_col[i];
197  }
198  else if (i == 0 && j > 0)
199  {
200  scr_diag = initial_row[j - 1];
201  scr_up = initial_row[j];
202  scr_left = score_mat[0][i][j - 1];
203  }
204  else if (i > 0 && j == 0)
205  {
206  scr_diag = initial_col[i - 1];
207  scr_up = score_mat[0][i - 1][j];
208  scr_left = initial_col[i];
209  }
210  else
211  {
212  scr_diag = score_mat[0][i - 1][j - 1];
213  scr_up = score_mat[0][i - 1][j];
214  scr_left = score_mat[0][i][j - 1];
215  }
216 
217  float m_score = scr_diag + (query[i] == reference[j] ? penalties.match : penalties.mismatch);
218  float d_score = scr_up + penalties.linear_gap;
219  float i_score = scr_left + penalties.linear_gap;
220 
221  float max_score = max(m_score, max(d_score, i_score));
222  score_mat[0][i][j] = max_score;
223 
224  // Choose the maximum score and update the traceback matrix
225  if (max_score == m_score)
226  {
227  tb_mat[i][j] = 'D'; // 'D' indicates a diagonal direction (match or mismatch)
228  }
229  else if (max_score == d_score)
230  {
231  tb_mat[i][j] = 'U'; // 'U' indicates an up direction (deletion)
232  }
233  else
234  {
235  tb_mat[i][j] = 'L'; // 'L' indicates a left direction (insertion)
236  }
237  }
238  }
239 
240  // Traceback to find the aligned sequences
241  int i = query.length() - 1;
242  int j = reference.length() - 1;
243  string aligned_query = "";
244  string aligned_reference = "";
245 
246  while (i >= 0 && j >= 0)
247  {
248  if (tb_mat[i][j] == 'D')
249  {
250  aligned_query = query[i] + aligned_query;
251  aligned_reference = reference[j] + aligned_reference;
252  i--;
253  j--;
254  }
255  else if (tb_mat[i][j] == 'U')
256  {
257  aligned_query = query[i] + aligned_query;
258  aligned_reference = "_" + aligned_reference;
259  i--;
260  }
261  else if (tb_mat[i][j] == 'L')
262  {
263  aligned_query = "_" + aligned_query;
264  aligned_reference = reference[j] + aligned_reference;
265  j--;
266  }
267  else
268  {
269  cout << "ERROR: Invalid traceback matrix value" << endl;
270  break;
271  }
272  }
273 
274  // Finish up the rest of the characters in the query and reference
275  while (i >= 0)
276  {
277  aligned_query = query[i] + aligned_query;
278  aligned_reference = "_" + aligned_reference;
279  i--;
280  }
281  while (j >= 0)
282  {
283  aligned_query = "_" + aligned_query;
284  aligned_reference = reference[j] + aligned_reference;
285  j--;
286  }
287 
288  alignments["query"] = aligned_query;
289  alignments["reference"] = aligned_reference;
290 }
291 
292 // >>> Banding Global Linear Solution >>>
293 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS, int SOL_BANDWIDTH>
294 void fixed_banding_global_linear_solution(std::string query, std::string reference, PENALTY_T &penalties,
295  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
296  array<array<char, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
297  map<string, string> &alignments)
298 {
299  // NOTE: we cannot augment the score matrix like this in the hardware since
300  // the initial scores for the following wavefronts will be shifted away in
301  // the dp_mem!
302 
303  // declare the intial column and row
304  array<float, SOL_MAX_QUERY_LENGTH> initial_col;
305  array<float, SOL_MAX_REFERENCE_LENGTH> initial_row;
306 
307  // initialize the initial column
308  float upper_left_value = 0;
309  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
310  {
311  upper_left_value += penalties.linear_gap; // since it was declared with type_t then convert back to int.
312  initial_col[i] = upper_left_value;
313  }
314 
315  // initialize the initial row
316  upper_left_value = 0; // FIXME: This might to be initialized as 0
317  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
318  {
319  upper_left_value += penalties.linear_gap; // since it was declared with type_t then convert back to int.
320  initial_row[j] = upper_left_value;
321  }
322 
323  // initialize the score_matrix
324  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
325  {
326  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
327  {
328  score_mat[0][i][j] = 0;
329  }
330  }
331 
332  // initialize the traceback matrix
333  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
334  {
335  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
336  {
337  tb_mat[i][j] = '*';
338  }
339  }
340 
341  int llim[SOL_MAX_QUERY_LENGTH], ulim[SOL_MAX_QUERY_LENGTH];
342  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
343  {
344  llim[i] = i - SOL_BANDWIDTH;
345  ulim[i] = i + SOL_BANDWIDTH - 1;
346  }
347 
348  // print ulim
349  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++) {
350  cout << ulim[i] << " ";
351 
352  }
353  cout << endl;
354 
355  // Fill in the DP matrix and traceback matrix
356  for (int i = 0; i < query.length(); i++)
357  {
358  int scr_diag, scr_up, scr_left;
359  for (int j = 0; j < reference.length(); j++)
360  {
361  if (j < llim[i])
362  continue;
363  if (j > ulim[i])
364  break;
365 
366  if (i == 0 && j == 0)
367  {
368  scr_diag = 0;
369  scr_up = initial_row[j];
370  scr_left = initial_col[i];
371  }
372  else if (i == 0 && j > 0)
373  {
374  scr_diag = initial_row[j - 1];
375  scr_up = initial_row[j];
376  scr_left = score_mat[0][i][j - 1];
377  }
378  else if (i > 0 && j == 0)
379  {
380  scr_diag = initial_col[i - 1];
381  scr_up = score_mat[0][i - 1][j];
382  scr_left = initial_col[i];
383  }
384  else
385  {
386  scr_diag = score_mat[0][i - 1][j - 1];
387  scr_up = score_mat[0][i - 1][j];
388  scr_left = score_mat[0][i][j - 1];
389  }
390 
391  if (j == llim[i])
392  {
393  scr_left = -std::numeric_limits<float>::infinity();
394  }
395  if (j == ulim[i])
396  {
397  scr_up = -std::numeric_limits<float>::infinity();
398  }
399 
400  float m_score = scr_diag + (query[i] == reference[j] ? penalties.match : penalties.mismatch);
401  float d_score = scr_up + penalties.linear_gap;
402  float i_score = scr_left + penalties.linear_gap;
403 
404  float max_score = m_score;
405  tb_mat[i][j] = 'D';
406  if (max_score < i_score)
407  {
408  max_score = i_score;
409  tb_mat[i][j] = 'L';
410  }
411  if (max_score < d_score)
412  {
413  max_score = d_score;
414  tb_mat[i][j] = 'U';
415  }
416 
417  score_mat[0][i][j] = max_score;
418 
419  }
420  }
421 
422  // Traceback to find the aligned sequences
423  int i = query.length() - 1;
424  int j = reference.length() - 1;
425  string aligned_query = "";
426  string aligned_reference = "";
427 
428  while (i >= 0 && j >= 0)
429  {
430  if (tb_mat[i][j] == 'D')
431  {
432  aligned_query = query[i] + aligned_query;
433  aligned_reference = reference[j] + aligned_reference;
434  i--;
435  j--;
436  }
437  else if (tb_mat[i][j] == 'U')
438  {
439  aligned_query = query[i] + aligned_query;
440  aligned_reference = "_" + aligned_reference;
441  i--;
442  }
443  else if (tb_mat[i][j] == 'L')
444  {
445  aligned_query = "_" + aligned_query;
446  aligned_reference = reference[j] + aligned_reference;
447  j--;
448  }
449  else
450  {
451  cout << "ERROR: Invalid traceback matrix value" << endl;
452  break;
453  }
454  }
455 
456  // Finish up the rest of the characters in the query and reference
457  while (i >= 0)
458  {
459  aligned_query = query[i] + aligned_query;
460  aligned_reference = "_" + aligned_reference;
461  i--;
462  }
463  while (j >= 0)
464  {
465  aligned_query = "_" + aligned_query;
466  aligned_reference = reference[j] + aligned_reference;
467  j--;
468  }
469 
470  alignments["query"] = aligned_query;
471  alignments["reference"] = aligned_reference;
472 }
473 
474 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS>
475 void global_affine_solution(std::string query, std::string reference, PENALTY_T &penalties,
476  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
477  array<array<string, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
478  map<string, string> &alignments)
479 {
480  const int N_LAYERS_GA = 3; // N_Layers for global affiner kernel
481 
482  // Layer 0: Insertion Matrix
483  // Layer 1: Match Mismatch Matrix
484  // Layer 2: Deletion Matrix
485 
486  // Declare initial column and row scores
487  array<array<float, N_LAYERS_GA>, SOL_MAX_QUERY_LENGTH> initial_col;
488  array<array<float, N_LAYERS_GA>, SOL_MAX_REFERENCE_LENGTH> initial_row;
489 
490  // Initialize intial column and row values
491  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
492  {
493  initial_col[i][0] = -std::numeric_limits<float>::infinity();
494  initial_col[i][1] = penalties.open + penalties.extend * (i + 1);
495  initial_col[i][2] = 0; // This can be whatever, since won't be accessed
496  }
497 
498  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
499  {
500  initial_row[j][0] = 0; // This can be whatever, since won't be accessed
501  initial_row[j][1] = penalties.open + penalties.extend * (j + 1);
502  initial_row[j][2] = -std::numeric_limits<float>::infinity();
503  }
504 
505  // Initialize the score matrix
506  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
507  {
508  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
509  {
510  for (int k = 0; k < N_LAYERS_GA; k++)
511  {
512  score_mat[k][i][j] = 0;
513  }
514  }
515  }
516 
517  // Initialize the traceback matrix
518  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
519  {
520  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
521  {
522  tb_mat[i][j] = '*';
523  }
524  }
525 
526  // Fill in the DP matrix and traceback matrix
527  for (int i = 0; i < query.length(); i++)
528  {
529  float del_scr, ins_scr;
530  float scr_diag, scr_up, scr_left;
531  for (int j = 0; j < reference.length(); j++)
532  {
533  if (i == 0 && j == 0)
534  {
535  scr_diag = 0;
536  scr_up = initial_row[j][1];
537  scr_left = initial_col[i][1];
538 
539  ins_scr = initial_col[i][0];
540  del_scr = initial_row[j][2];
541  }
542  else if (i == 0 && j > 0)
543  {
544  scr_diag = initial_row[j - 1][1];
545  scr_up = initial_row[j][1];
546  scr_left = score_mat[1][i][j - 1];
547 
548  ins_scr = score_mat[0][i][j - 1];
549  del_scr = initial_row[j][2];
550  }
551  else if (i > 0 && j == 0)
552  {
553  scr_diag = initial_col[i - 1][1];
554  scr_up = score_mat[1][i - 1][j];
555  scr_left = initial_col[i][1];
556 
557  ins_scr = initial_col[i][0];
558  del_scr = score_mat[2][i - 1][j];
559  }
560  else
561  {
562  scr_diag = score_mat[1][i - 1][j - 1];
563  scr_up = score_mat[1][i - 1][j];
564  scr_left = score_mat[1][i][j - 1];
565 
566  ins_scr = score_mat[0][i][j - 1];
567  del_scr = score_mat[2][i - 1][j];
568  }
569 
570  float insertion_open_score = scr_left + penalties.open + penalties.extend;
571  float insertion_extend_score = ins_scr + penalties.extend;
572 
573  float deletion_open_score = scr_up + penalties.open + penalties.extend;
574  float deletion_extend_score = del_scr + penalties.extend;
575 
576  float mm_score = scr_diag + (query[i] == reference[j] ? penalties.match : penalties.mismatch);
577 
578  float insertion_score = insertion_open_score > insertion_extend_score ? insertion_open_score : insertion_extend_score;
579  float deletion_score = deletion_open_score > deletion_extend_score ? deletion_open_score : deletion_extend_score;
580 
581  float final_score = insertion_score > deletion_score ? insertion_score : deletion_score;
582  final_score = final_score > mm_score ? final_score : mm_score;
583 
584  score_mat[0][i][j] = insertion_score;
585  score_mat[1][i][j] = final_score;
586  score_mat[2][i][j] = deletion_score;
587 
588  // Choose the maximum score and update the traceback matrix
589  if (final_score == insertion_score)
590  {
591  tb_mat[i][j] = insertion_score == insertion_open_score ? "L " : "LE"; // 'L' indicates a left direction (insertion)
592  }
593  else if (final_score == deletion_score)
594  {
595  tb_mat[i][j] = deletion_score == deletion_open_score ? "U " : "UE"; // 'U' indicates an up direction (deletion)
596  }
597  else if (final_score == mm_score)
598  {
599  tb_mat[i][j] = "D "; // 'D' indicates a diagonal direction (match or mismatch)
600  }
601  else
602  {
603  cout << "ERROR: Invalid traceback matrix value" << endl;
604  break;
605  }
606  }
607  }
608 
609  // Traceback to find the aligned sequences
610  int i = query.length() - 1;
611  int j = reference.length() - 1;
612  string aligned_query = "";
613  string aligned_reference = "";
614  while (i >= 0 && j >= 0)
615  {
616  if (tb_mat[i][j] == "D ")
617  {
618  aligned_query = query[i] + aligned_query;
619  aligned_reference = reference[j] + aligned_reference;
620  i--;
621  j--;
622  }
623  else if (tb_mat[i][j] == "U ")
624  {
625  aligned_query = query[i] + aligned_query;
626  aligned_reference = "_" + aligned_reference;
627  i--;
628  }
629  else if (tb_mat[i][j] == "UE")
630  {
631  aligned_query = query[i] + aligned_query;
632  aligned_reference = "_" + aligned_reference;
633  i--;
634  }
635  else if (tb_mat[i][j] == "L ")
636  {
637  aligned_query = "_" + aligned_query;
638  aligned_reference = reference[j] + aligned_reference;
639  j--;
640  }
641  else if (tb_mat[i][j] == "LE")
642  {
643  aligned_query = "_" + aligned_query;
644  aligned_reference = reference[j] + aligned_reference;
645  j--;
646  }
647  else
648  {
649  cout << "ERROR: Invalid traceback matrix value" << endl;
650  break;
651  }
652  }
653 
654  // Finish up the rest of the characters in the query and reference
655  while (i >= 0)
656  {
657  aligned_query = query[i] + aligned_query;
658  aligned_reference = "_" + aligned_reference;
659  i--;
660  }
661  while (j >= 0)
662  {
663  aligned_query = "_" + aligned_query;
664  aligned_reference = reference[j] + aligned_reference;
665  j--;
666  }
667 
668  alignments["query"] = aligned_query;
669  alignments["reference"] = aligned_reference;
670 }
671 
672 // Write a local linear solution, which is similar to the global linear solution. The difference is that the local linear solution start
673 // the traceback from the cell with the highets score and ends where the score drop below 0.
674 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS>
675 void local_linear_solution(std::string query, std::string reference, PENALTY_T &penalties,
676  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
677  array<array<char, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
678  map<string, string> &alignments)
679 {
680  // NOTE: we cannot augment the score matrix like this in the hardware since
681  // the initial scores for the following wavefronts will be shifted away in
682  // the dp_mem!
683 
684  // declare the intial column and row
685  array<float, SOL_MAX_QUERY_LENGTH> initial_col;
686  array<float, SOL_MAX_REFERENCE_LENGTH> initial_row;
687 
688  // initialize the initial column
689  float upper_left_value = 0;
690  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
691  {
692  upper_left_value += 0; // since it was declared with type_t then convert back to int.
693  initial_col[i] = upper_left_value;
694  }
695 
696  // initialize the initial row
697  upper_left_value = 0; // FIXME: This might to be initialized as 0
698  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
699  {
700  upper_left_value += 0; // since it was declared with type_t then convert back to int.
701  initial_row[j] = upper_left_value;
702  }
703 
704  // initialize the score_matrix
705  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
706  {
707  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
708  {
709  score_mat[0][i][j] = 0;
710  }
711  }
712 
713  // initialize the traceback matrix
714  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
715  {
716  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
717  {
718  tb_mat[i][j] = '*';
719  }
720  }
721 
722  float global_max_score = 0;
723  int max_row = 0;
724  int max_col = 0;
725 
726  // Fill in the DP matrix and traceback matrix
727  for (int i = 0; i < query.length(); i++)
728  {
729  int scr_diag, scr_up, scr_left;
730  for (int j = 0; j < reference.length(); j++)
731  {
732  if (i == 0 && j == 0)
733  {
734  scr_diag = 0;
735  scr_up = initial_row[j];
736  scr_left = initial_col[i];
737  }
738  else if (i == 0 && j > 0)
739  {
740  scr_diag = initial_row[j - 1];
741  scr_up = initial_row[j];
742  scr_left = score_mat[0][i][j - 1];
743  }
744  else if (i > 0 && j == 0)
745  {
746  scr_diag = initial_col[i - 1];
747  scr_up = score_mat[0][i - 1][j];
748  scr_left = initial_col[i];
749  }
750  else
751  {
752  scr_diag = score_mat[0][i - 1][j - 1];
753  scr_up = score_mat[0][i - 1][j];
754  scr_left = score_mat[0][i][j - 1];
755  }
756 
757  float m_score = scr_diag + (query[i] == reference[j] ? penalties.match : penalties.mismatch);
758  float d_score = scr_up + penalties.linear_gap;
759  float i_score = scr_left + penalties.linear_gap;
760 
761  float max_score = max(max(m_score, max(d_score, i_score)), (float)0);
762  score_mat[0][i][j] = max_score;
763 
764  if (max_score > global_max_score)
765  {
766  global_max_score = max_score;
767  max_row = i;
768  max_col = j;
769  }
770 
771  // Choose the maximum score and update the traceback matrix
772  if (max_score == i_score)
773  {
774  tb_mat[i][j] = 'L'; // 'L' indicates a left direction (insertion)
775  }
776  else if (max_score == m_score)
777  {
778  tb_mat[i][j] = 'D'; // 'D' indicates a diagonal direction (match or mismatch)
779  }
780  else if (max_score == d_score)
781  {
782  tb_mat[i][j] = 'U'; // 'U' indicates an up direction (deletion)
783  }
784  else
785  {
786  tb_mat[i][j] = '*';
787  }
788  }
789  }
790 
791  // Traceback to find the aligned sequences
792  int i = max_row;
793  int j = max_col;
794  string aligned_query = "";
795  string aligned_reference = "";
796 
797  while (i >= 0 && j >= 0)
798  {
799  if (tb_mat[i][j] == 'D')
800  {
801  aligned_query = query[i] + aligned_query;
802  aligned_reference = reference[j] + aligned_reference;
803  i--;
804  j--;
805  }
806  else if (tb_mat[i][j] == 'U')
807  {
808  aligned_query = query[i] + aligned_query;
809  aligned_reference = "_" + aligned_reference;
810  i--;
811  }
812  else if (tb_mat[i][j] == 'L')
813  {
814  aligned_query = "_" + aligned_query;
815  aligned_reference = reference[j] + aligned_reference;
816  j--;
817  }
818  else if (tb_mat[i][j] == '*')
819  {
820  i--;
821  j--;
822  break;
823  }
824  else
825  {
826  cout << "ERROR: Invalid traceback matrix value" << endl;
827  break;
828  }
829  }
830 
831  // Finish up the rest of the characters in the query and reference
832  while (i >= 0)
833  {
834  aligned_query = query[i] + aligned_query;
835  aligned_reference = "_" + aligned_reference;
836  i--;
837  }
838  while (j >= 0)
839  {
840  aligned_query = "_" + aligned_query;
841  aligned_reference = reference[j] + aligned_reference;
842  j--;
843  }
844 
845  alignments["query"] = aligned_query;
846  alignments["reference"] = aligned_reference;
847 }
848 
849 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS>
850 void local_affine_solution(std::string query, std::string reference, PENALTY_T &penalties,
851  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
852  array<array<string, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
853  map<string, string> &alignments)
854 {
855  const int N_LAYERS_GA = 3; // N_Layers for global affiner kernel
856 
857  // Layer 0: Insertion Matrix
858  // Layer 1: Match Mismatch Matrix
859  // Layer 2: Deletion Matrix
860 
861  // Declare initial column and row scores
862  array<array<float, N_LAYERS_GA>, SOL_MAX_QUERY_LENGTH> initial_col;
863  array<array<float, N_LAYERS_GA>, SOL_MAX_REFERENCE_LENGTH> initial_row;
864 
865  // Initialize intial column and row values
866  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
867  {
868  initial_col[i][0] = -std::numeric_limits<float>::infinity();
869  initial_col[i][1] = 0;
870  initial_col[i][2] = 0; // This can be whatever, since won't be accessed
871  }
872 
873  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
874  {
875  initial_row[j][0] = 0; // This can be whatever, since won't be accessed
876  initial_row[j][1] = 0;
877  initial_row[j][2] = -std::numeric_limits<float>::infinity();
878  }
879 
880  // Initialize the score matrix
881  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
882  {
883  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
884  {
885  for (int k = 0; k < N_LAYERS_GA; k++)
886  {
887  score_mat[k][i][j] = 0;
888  }
889  }
890  }
891 
892  // Initialize the traceback matrix
893  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
894  {
895  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
896  {
897  tb_mat[i][j] = '*';
898  }
899  }
900 
901  float maximum_score = -std::numeric_limits<float>::infinity();
902  int max_i = 0;
903  int max_j = 0;
904 
905  // Fill in the DP matrix and traceback matrix
906  for (int i = 0; i < query.length(); i++)
907  {
908  float del_scr, ins_scr;
909  float scr_diag, scr_up, scr_left;
910  for (int j = 0; j < reference.length(); j++)
911  {
912  if (i == 0 && j == 0)
913  {
914  scr_diag = 0;
915  scr_up = initial_row[j][1];
916  scr_left = initial_col[i][1];
917 
918  ins_scr = initial_col[i][0];
919  del_scr = initial_row[j][2];
920  }
921  else if (i == 0 && j > 0)
922  {
923  scr_diag = initial_row[j - 1][1];
924  scr_up = initial_row[j][1];
925  scr_left = score_mat[1][i][j - 1];
926 
927  ins_scr = score_mat[0][i][j - 1];
928  del_scr = initial_row[j][2];
929  }
930  else if (i > 0 && j == 0)
931  {
932  scr_diag = initial_col[i - 1][1];
933  scr_up = score_mat[1][i - 1][j];
934  scr_left = initial_col[i][1];
935 
936  ins_scr = initial_col[i][0];
937  del_scr = score_mat[2][i - 1][j];
938  }
939  else
940  {
941  scr_diag = score_mat[1][i - 1][j - 1];
942  scr_up = score_mat[1][i - 1][j];
943  scr_left = score_mat[1][i][j - 1];
944 
945  ins_scr = score_mat[0][i][j - 1];
946  del_scr = score_mat[2][i - 1][j];
947  }
948 
949  float insertion_open_score = scr_left + penalties.open + penalties.extend;
950  float insertion_extend_score = ins_scr + penalties.extend;
951 
952  float deletion_open_score = scr_up + penalties.open + penalties.extend;
953  float deletion_extend_score = del_scr + penalties.extend;
954 
955  float mm_score = scr_diag + (query[i] == reference[j] ? penalties.match : penalties.mismatch);
956 
957  float insertion_score = insertion_open_score > insertion_extend_score ? insertion_open_score : insertion_extend_score;
958  float deletion_score = deletion_open_score > deletion_extend_score ? deletion_open_score : deletion_extend_score;
959 
960  // float final_score = max(mm_score, max(insertion_score, deletion_score));
961  // final_score = max((float)0.0, final_score);
962  float max_score = insertion_score > deletion_score ? insertion_score : deletion_score;
963  max_score = max_score > mm_score ? max_score : mm_score;
964  max_score = max_score >= 0 ? max_score : 0;
965 
966  if (max_score > maximum_score)
967  {
968  maximum_score = max_score;
969  max_i = i;
970  max_j = j;
971  }
972 
973  score_mat[0][i][j] = insertion_score;
974  score_mat[1][i][j] = max_score;
975  score_mat[2][i][j] = deletion_score;
976 
977  // Choose the maximum score and update the traceback matrix
978  if (max_score == insertion_score)
979  {
980  tb_mat[i][j] = insertion_score == insertion_open_score ? "L " : "LE"; // 'L' indicates a left direction (insertion)
981  }
982  else if (max_score == deletion_score)
983  {
984  tb_mat[i][j] = deletion_score == deletion_open_score ? "U " : "UE"; // 'U' indicates an up direction (deletion)
985  }
986  else if (max_score == mm_score)
987  {
988  tb_mat[i][j] = "D "; // 'D' indicates a diagonal direction (match or mismatch)
989  }
990  else if (max_score == 0)
991  {
992  tb_mat[i][j] = "*";
993  }
994  else
995  {
996  cout << "ERROR: Invalid traceback matrix value" << endl;
997  break;
998  }
999  }
1000  }
1001 
1002  // Traceback to find the aligned sequences
1003  int i = max_i;
1004  int j = max_j;
1005  string aligned_query = "";
1006  string aligned_reference = "";
1007  while (i >= 0 && j >= 0)
1008  {
1009  if (tb_mat[i][j] == "D ")
1010  {
1011  aligned_query = query[i] + aligned_query;
1012  aligned_reference = reference[j] + aligned_reference;
1013  i--;
1014  j--;
1015  }
1016  else if (tb_mat[i][j] == "U ")
1017  {
1018  aligned_query = query[i] + aligned_query;
1019  aligned_reference = "_" + aligned_reference;
1020  i--;
1021  }
1022  else if (tb_mat[i][j] == "UE")
1023  {
1024  aligned_query = query[i] + aligned_query;
1025  aligned_reference = "_" + aligned_reference;
1026  i--;
1027  }
1028  else if (tb_mat[i][j] == "L ")
1029  {
1030  aligned_query = "_" + aligned_query;
1031  aligned_reference = reference[j] + aligned_reference;
1032  j--;
1033  }
1034  else if (tb_mat[i][j] == "LE")
1035  {
1036  aligned_query = "_" + aligned_query;
1037  aligned_reference = reference[j] + aligned_reference;
1038  j--;
1039  }
1040  else if (tb_mat[i][j] == "*")
1041  {
1042  i--;
1043  j--;
1044  break;
1045  }
1046  else
1047  {
1048  cout << "ERROR: Invalid traceback matrix value" << endl;
1049  break;
1050  }
1051  }
1052 
1053  // Finish up the rest of the characters in the query and reference
1054  while (i >= 0)
1055  {
1056  aligned_query = query[i] + aligned_query;
1057  aligned_reference = "_" + aligned_reference;
1058  i--;
1059  }
1060  while (j >= 0)
1061  {
1062  aligned_query = "_" + aligned_query;
1063  aligned_reference = reference[j] + aligned_reference;
1064  j--;
1065  }
1066 
1067  alignments["query"] = aligned_query;
1068  alignments["reference"] = aligned_reference;
1069 }
1070 
1074 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS>
1075 void semi_global_linear_long_short_solution(std::string query, std::string reference, PENALTY_T &penalties,
1076  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
1077  array<array<char, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
1078  map<string, string> &alignments)
1079 {
1080  // assume using linear gap penalties
1081 
1082  // declare the intial column and row
1083  array<float, SOL_MAX_QUERY_LENGTH> initial_col;
1084  array<float, SOL_MAX_REFERENCE_LENGTH> initial_row;
1085 
1086  float upper_left_value = 0;
1087  // initialize the initial column
1088  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1089  {
1090  // upper_left_value += penalties.open; // since it was declared with type_t then convert back to int.
1091  initial_col[i] = upper_left_value;
1092  }
1093 
1094  // initialize the initial row
1095  upper_left_value = 0; // FIXME: This might to be initialized as 0
1096  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1097  {
1098  upper_left_value += penalties.linear_gap; // since it was declared with type_t then convert back to int.
1099  initial_row[j] = upper_left_value;
1100  }
1101 
1102  // initialize the score_matrix
1103  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1104  {
1105  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1106  {
1107  score_mat[0][i][j] = 0;
1108  }
1109  }
1110 
1111  // initialize the traceback matrix
1112  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1113  {
1114  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1115  {
1116  tb_mat[i][j] = '*';
1117  }
1118  }
1119 
1120  // Fill in the DP matrix and traceback matrix
1121  for (int i = 0; i < query.length(); i++)
1122  {
1123  int scr_diag, scr_up, scr_left;
1124  for (int j = 0; j < reference.length(); j++)
1125  {
1126  if (i == 0 && j == 0)
1127  {
1128  scr_diag = 0;
1129  scr_up = initial_row[j];
1130  scr_left = initial_col[i];
1131  }
1132  else if (i == 0 && j > 0)
1133  {
1134  scr_diag = initial_row[j - 1];
1135  scr_up = initial_row[j];
1136  scr_left = score_mat[0][i][j - 1];
1137  }
1138  else if (i > 0 && j == 0)
1139  {
1140  scr_diag = initial_col[i - 1];
1141  scr_up = score_mat[0][i - 1][j];
1142  scr_left = initial_col[i];
1143  }
1144  else
1145  {
1146  scr_diag = score_mat[0][i - 1][j - 1];
1147  scr_up = score_mat[0][i - 1][j];
1148  scr_left = score_mat[0][i][j - 1];
1149  }
1150 
1151  float m_score = scr_diag + (query[i] == reference[j] ? penalties.match : penalties.mismatch);
1152  float d_score = scr_up + penalties.linear_gap;
1153  float i_score = scr_left + penalties.linear_gap;
1154 
1155  float max_score = max(m_score, max(d_score, i_score));
1156  score_mat[0][i][j] = max_score;
1157 
1158  // Choose the maximum score and update the traceback matrix
1159  if (max_score == m_score)
1160  {
1161  tb_mat[i][j] = 'D'; // 'D' indicates a diagonal direction (match or mismatch)
1162  }
1163  else if (max_score == d_score)
1164  {
1165  tb_mat[i][j] = 'U'; // 'U' indicates an up direction (deletion)
1166  }
1167  else
1168  {
1169  tb_mat[i][j] = 'L'; // 'L' indicates a left direction (insertion)
1170  }
1171  }
1172  }
1173 
1174  // Traceback to find the aligned sequences
1175  float maxVal;
1176  std::pair<int, int> maxPos;
1177 
1178  // check for max value in the rightmost column
1179  maxVal = score_mat[0][SOL_MAX_QUERY_LENGTH - 1][SOL_MAX_REFERENCE_LENGTH - 1];
1180  maxPos = {SOL_MAX_QUERY_LENGTH - 1, SOL_MAX_REFERENCE_LENGTH - 1};
1181  for (int j = SOL_MAX_QUERY_LENGTH - 1; j >= 0; j--)
1182  {
1183  if (score_mat[0][j][SOL_MAX_REFERENCE_LENGTH - 1] > maxVal)
1184  {
1185  maxVal = score_mat[0][j][SOL_MAX_REFERENCE_LENGTH - 1];
1186  maxPos = {j, SOL_MAX_REFERENCE_LENGTH - 1};
1187  }
1188  }
1189  int i = maxPos.first;
1190  int j = maxPos.second;
1191  string aligned_query = "";
1192  string aligned_reference = "";
1193 
1194  while (i >= 0 && j >= 0)
1195  {
1196  if (tb_mat[i][j] == 'D')
1197  {
1198  aligned_query = query[i] + aligned_query;
1199  aligned_reference = reference[j] + aligned_reference;
1200  i--;
1201  j--;
1202  }
1203  else if (tb_mat[i][j] == 'U')
1204  {
1205  aligned_query = query[i] + aligned_query;
1206  aligned_reference = "_" + aligned_reference;
1207  i--;
1208  }
1209  else if (tb_mat[i][j] == 'L')
1210  {
1211  aligned_query = "_" + aligned_query;
1212  aligned_reference = reference[j] + aligned_reference;
1213  j--;
1214  }
1215  else
1216  {
1217  cout << "ERROR: Invalid traceback matrix value" << endl;
1218  break;
1219  }
1220  }
1221 
1222  // Finish up the rest of the characters in the query and reference
1223  while (i >= 0)
1224  {
1225  aligned_query = query[i] + aligned_query;
1226  aligned_reference = "_" + aligned_reference;
1227  i--;
1228  }
1229  while (j >= 0)
1230  {
1231  aligned_query = "_" + aligned_query;
1232  aligned_reference = reference[j] + aligned_reference;
1233  j--;
1234  }
1235 
1236  alignments["query"] = aligned_query;
1237  alignments["reference"] = aligned_reference;
1238 }
1239 
1243 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS>
1244 void semi_global_linear_short_long_solution(std::string query, std::string reference, PENALTY_T &penalties,
1245  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
1246  array<array<char, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
1247  map<string, string> &alignments)
1248 {
1249  // assume using linear gap penalties
1250 
1251  // declare the intial column and row
1252  array<float, SOL_MAX_QUERY_LENGTH> initial_col;
1253  array<float, SOL_MAX_REFERENCE_LENGTH> initial_row;
1254 
1255  float upper_left_value = 0;
1256  // initialize the initial column
1257  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1258  {
1259  upper_left_value += penalties.linear_gap; // since it was declared with type_t then convert back to int.
1260  initial_col[i] = upper_left_value;
1261  }
1262 
1263  // initialize the initial row
1264  upper_left_value = 0;
1265  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1266  {
1267  initial_row[j] = upper_left_value;
1268  }
1269 
1270  // initialize the score_matrix
1271  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1272  {
1273  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1274  {
1275  score_mat[0][i][j] = 0;
1276  }
1277  }
1278 
1279  // initialize the traceback matrix
1280  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1281  {
1282  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1283  {
1284  tb_mat[i][j] = '*';
1285  }
1286  }
1287 
1288  // Fill in the DP matrix and traceback matrix
1289  for (int i = 0; i < query.length(); i++)
1290  {
1291  int scr_diag, scr_up, scr_left;
1292  for (int j = 0; j < reference.length(); j++)
1293  {
1294  if (i == 0 && j == 0)
1295  {
1296  scr_diag = 0;
1297  scr_up = initial_row[j];
1298  scr_left = initial_col[i];
1299  }
1300  else if (i == 0 && j > 0)
1301  {
1302  scr_diag = initial_row[j - 1];
1303  scr_up = initial_row[j];
1304  scr_left = score_mat[0][i][j - 1];
1305  }
1306  else if (i > 0 && j == 0)
1307  {
1308  scr_diag = initial_col[i - 1];
1309  scr_up = score_mat[0][i - 1][j];
1310  scr_left = initial_col[i];
1311  }
1312  else
1313  {
1314  scr_diag = score_mat[0][i - 1][j - 1];
1315  scr_up = score_mat[0][i - 1][j];
1316  scr_left = score_mat[0][i][j - 1];
1317  }
1318 
1319  float m_score = scr_diag + (query[i] == reference[j] ? penalties.match : penalties.mismatch);
1320  float d_score = scr_up + penalties.linear_gap;
1321  float i_score = scr_left + penalties.linear_gap;
1322 
1323  float max_score = max(m_score, max(d_score, i_score));
1324  score_mat[0][i][j] = max_score;
1325 
1326  // Choose the maximum score and update the traceback matrix
1327  if (max_score == m_score)
1328  {
1329  tb_mat[i][j] = 'D'; // 'D' indicates a diagonal direction (match or mismatch)
1330  }
1331  else if (max_score == d_score)
1332  {
1333  tb_mat[i][j] = 'U'; // 'U' indicates an up direction (deletion)
1334  }
1335  else
1336  {
1337  tb_mat[i][j] = 'L'; // 'L' indicates a left direction (insertion)
1338  }
1339  }
1340  }
1341 
1342  // Traceback to find the aligned sequences
1343  float maxVal = score_mat[0][query.size() - 1][0];
1344  std::pair<int, int> maxPos = {query.size() - 1, 0};
1345 
1346  // check for max value in the bottom row
1347  for (int i = 0; i < reference.size() - 1; i++)
1348  {
1349  if (score_mat[0][query.size() - 1][i] > maxVal)
1350  {
1351  maxVal = score_mat[0][query.size() - 1][i];
1352  maxPos = {query.size() - 1, i};
1353  }
1354  }
1355 
1356  string aligned_query = "";
1357  string aligned_reference = "";
1358 
1359  int i = maxPos.first;
1360  int j = maxPos.second;
1361 
1362 
1363  while (i >= 0 && j >= 0)
1364  {
1365  if (tb_mat[i][j] == 'D')
1366  {
1367  aligned_query = query[i] + aligned_query;
1368  aligned_reference = reference[j] + aligned_reference;
1369  i--;
1370  j--;
1371  }
1372  else if (tb_mat[i][j] == 'U')
1373  {
1374  aligned_query = query[i] + aligned_query;
1375  aligned_reference = "_" + aligned_reference;
1376  i--;
1377  }
1378  else if (tb_mat[i][j] == 'L')
1379  {
1380  aligned_query = "_" + aligned_query;
1381  aligned_reference = reference[j] + aligned_reference;
1382  j--;
1383  }
1384  else
1385  {
1386  cout << "ERROR: Invalid traceback matrix value" << tb_mat[i][j] << endl;
1387  break;
1388  }
1389  }
1390 
1391  // Finish up the rest of the characters in the query and reference
1392  while (i >= 0)
1393  {
1394  aligned_query = query[i] + aligned_query;
1395  aligned_reference = "_" + aligned_reference;
1396  i--;
1397  }
1398  while (j >= 0)
1399  {
1400  aligned_query = "_" + aligned_query;
1401  aligned_reference = reference[j] + aligned_reference;
1402  j--;
1403  }
1404 
1405  alignments["query"] = aligned_query;
1406  alignments["reference"] = aligned_reference;
1407 }
1408 
1412 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS>
1413 void overlap_linear_prefix_suffix_solution(std::string query, std::string reference, PENALTY_T &penalties,
1414  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
1415  array<array<char, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
1416  map<string, string> &alignments)
1417 {
1418  // NOTE: we cannot augment the score matrix like this in the hardware since
1419  // the initial scores for the following wavefronts will be shifted away in
1420  // the dp_mem!
1421 
1422  // declare the intial column and row
1423  array<float, SOL_MAX_QUERY_LENGTH> initial_col;
1424  array<float, SOL_MAX_REFERENCE_LENGTH> initial_row;
1425 
1426  float upper_left_value = 0;
1427  // initialize the column
1428  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1429  {
1430  // upper_left_value += penalties.open; // since it was declared with type_t then convert back to int.
1431  initial_col[i] = upper_left_value;
1432  }
1433  // initialize the initial row
1434  upper_left_value = 0;
1435  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1436  {
1437  upper_left_value += penalties.linear_gap; // since it was declared with type_t then convert back to int.
1438  initial_row[j] = upper_left_value;
1439  }
1440  // initialize the score_matrix
1441  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1442  {
1443  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1444  {
1445  score_mat[0][i][j] = 0;
1446  }
1447  }
1448 
1449  // initialize the traceback matrix
1450  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1451  {
1452  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1453  {
1454  tb_mat[i][j] = '*';
1455  }
1456  }
1457 
1458  // Fill in the DP matrix and traceback matrix
1459  for (int i = 0; i < query.length(); i++)
1460  {
1461  int scr_diag, scr_up, scr_left;
1462  for (int j = 0; j < reference.length(); j++)
1463  {
1464  if (i == 0 && j == 0)
1465  {
1466  scr_diag = 0;
1467  scr_up = initial_row[j];
1468  scr_left = initial_col[i];
1469  }
1470  else if (i == 0 && j > 0)
1471  {
1472  scr_diag = initial_row[j - 1];
1473  scr_up = initial_row[j];
1474  scr_left = score_mat[0][i][j - 1];
1475  }
1476  else if (i > 0 && j == 0)
1477  {
1478  scr_diag = initial_col[i - 1];
1479  scr_up = score_mat[0][i - 1][j];
1480  scr_left = initial_col[i];
1481  }
1482  else
1483  {
1484  scr_diag = score_mat[0][i - 1][j - 1];
1485  scr_up = score_mat[0][i - 1][j];
1486  scr_left = score_mat[0][i][j - 1];
1487  }
1488 
1489  float m_score = scr_diag + (query[i] == reference[j] ? penalties.match : penalties.mismatch);
1490  float d_score = scr_up + penalties.linear_gap;
1491  float i_score = scr_left + penalties.linear_gap;
1492 
1493  float max_score = max(m_score, max(d_score, i_score));
1494  score_mat[0][i][j] = max_score;
1495 
1496  // Choose the maximum score and update the traceback matrix
1497  if (max_score == m_score)
1498  {
1499  tb_mat[i][j] = 'D'; // 'D' indicates a diagonal direction (match or mismatch)
1500  }
1501  else if (max_score == d_score)
1502  {
1503  tb_mat[i][j] = 'U'; // 'U' indicates an up direction (deletion)
1504  }
1505  else
1506  {
1507  tb_mat[i][j] = 'L'; // 'L' indicates a left direction (insertion)
1508  }
1509  }
1510  }
1511 
1512  // Traceback to find the aligned sequences
1513  // Initialize the max value to be the bottom leftmost value
1514  float maxVal = score_mat[0][SOL_MAX_QUERY_LENGTH - 1][0];
1515  std::pair<int, int> maxPos = {SOL_MAX_QUERY_LENGTH - 1, 0};
1516 
1517  // check for max value in the bottom row
1518  for (int i = 0; i < SOL_MAX_REFERENCE_LENGTH; i++)
1519  {
1520  if (score_mat[0][SOL_MAX_QUERY_LENGTH - 1][i] > maxVal)
1521  {
1522  maxVal = score_mat[0][SOL_MAX_QUERY_LENGTH - 1][i];
1523  maxPos = {SOL_MAX_QUERY_LENGTH - 1, i};
1524  }
1525  }
1526  int i = maxPos.first;
1527  int j = maxPos.second;
1528  string aligned_query = "";
1529  string aligned_reference = "";
1530 
1531  while (i >= 0 && j >= 0)
1532  {
1533  if (tb_mat[i][j] == 'D')
1534  {
1535  aligned_query = query[i] + aligned_query;
1536  aligned_reference = reference[j] + aligned_reference;
1537  i--;
1538  j--;
1539  }
1540  else if (tb_mat[i][j] == 'U')
1541  {
1542  aligned_query = query[i] + aligned_query;
1543  aligned_reference = "_" + aligned_reference;
1544  i--;
1545  }
1546  else if (tb_mat[i][j] == 'L')
1547  {
1548  aligned_query = "_" + aligned_query;
1549  aligned_reference = reference[j] + aligned_reference;
1550  j--;
1551  }
1552  else
1553  {
1554  cout << "ERROR: Invalid traceback matrix value" << endl;
1555  break;
1556  }
1557  }
1558 
1559  // Finish up the rest of the characters in the query and reference
1560  while (i >= 0)
1561  {
1562  aligned_query = query[i] + aligned_query;
1563  aligned_reference = "_" + aligned_reference;
1564  i--;
1565  }
1566  while (j >= 0)
1567  {
1568  aligned_query = "_" + aligned_query;
1569  aligned_reference = reference[j] + aligned_reference;
1570  j--;
1571  }
1572 
1573  alignments["query"] = aligned_query;
1574  alignments["reference"] = aligned_reference;
1575 }
1576 
1580 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS>
1581 void overlap_linear_suffix_prefix_solution(std::string query, std::string reference, PENALTY_T &penalties,
1582  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
1583  array<array<char, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
1584  map<string, string> &alignments)
1585 {
1586 
1587  // declare the intial column and row
1588  array<float, SOL_MAX_QUERY_LENGTH> initial_col;
1589  array<float, SOL_MAX_REFERENCE_LENGTH> initial_row;
1590 
1591  float upper_left_value = 0;
1592  // initialize the initial column
1593  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1594  {
1595  upper_left_value += penalties.linear_gap; // since it was declared with type_t then convert back to int.
1596  initial_col[i] = upper_left_value;
1597  }
1598  // initialize the initial row
1599  upper_left_value = 0;
1600  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1601  {
1602  // upper_left_value += penalties.open; // since it was declared with type_t then convert back to int.
1603  initial_row[j] = upper_left_value;
1604  }
1605  // initialize the score_matrix
1606  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1607  {
1608  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1609  {
1610  score_mat[0][i][j] = 0;
1611  }
1612  }
1613 
1614  // initialize the traceback matrix
1615  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1616  {
1617  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1618  {
1619  tb_mat[i][j] = '*';
1620  }
1621  }
1622 
1623  // Fill in the DP matrix and traceback matrix
1624  for (int i = 0; i < query.length(); i++)
1625  {
1626  int scr_diag, scr_up, scr_left;
1627  for (int j = 0; j < reference.length(); j++)
1628  {
1629  if (i == 0 && j == 0)
1630  {
1631  scr_diag = 0;
1632  scr_up = initial_row[j];
1633  scr_left = initial_col[i];
1634  }
1635  else if (i == 0 && j > 0)
1636  {
1637  scr_diag = initial_row[j - 1];
1638  scr_up = initial_row[j];
1639  scr_left = score_mat[0][i][j - 1];
1640  }
1641  else if (i > 0 && j == 0)
1642  {
1643  scr_diag = initial_col[i - 1];
1644  scr_up = score_mat[0][i - 1][j];
1645  scr_left = initial_col[i];
1646  }
1647  else
1648  {
1649  scr_diag = score_mat[0][i - 1][j - 1];
1650  scr_up = score_mat[0][i - 1][j];
1651  scr_left = score_mat[0][i][j - 1];
1652  }
1653 
1654  float m_score = scr_diag + (query[i] == reference[j] ? penalties.match : penalties.mismatch);
1655  float d_score = scr_up + penalties.linear_gap;
1656  float i_score = scr_left + penalties.linear_gap;
1657 
1658  float max_score = max(m_score, max(d_score, i_score));
1659  score_mat[0][i][j] = max_score;
1660 
1661  // Choose the maximum score and update the traceback matrix
1662  if (max_score == m_score)
1663  {
1664  tb_mat[i][j] = 'D'; // 'D' indicates a diagonal direction (match or mismatch)
1665  }
1666  else if (max_score == d_score)
1667  {
1668  tb_mat[i][j] = 'U'; // 'U' indicates an up direction (deletion)
1669  }
1670  else
1671  {
1672  tb_mat[i][j] = 'L'; // 'L' indicates a left direction (insertion)
1673  }
1674  }
1675  }
1676 
1677  // Traceback to find the aligned sequences
1678  // Initialize the max value to be the top rightmost value
1679  float maxVal = score_mat[0][0][reference.length() - 1];
1680  std::pair<int, int> maxPos = {query.length() - 1, reference.length() - 1};
1681 
1682  // check for max value in the rightmost column
1683  for (int i = 0; i < query.length(); i++)
1684  {
1685  if (score_mat[0][i][reference.length() - 1] > maxVal)
1686  {
1687  maxVal = score_mat[0][i][reference.length() - 1];
1688  maxPos = {i, reference.length() - 1};
1689  }
1690  }
1691  int i = maxPos.first;
1692  int j = maxPos.second;
1693  cout << "i is " << i << endl;
1694  cout << "j is " << j << endl;
1695  string aligned_query = "";
1696  string aligned_reference = "";
1697 
1698  while (i >= 0 && j >= 0)
1699  {
1700  if (tb_mat[i][j] == 'D')
1701  {
1702  aligned_query = query[i] + aligned_query;
1703  aligned_reference = reference[j] + aligned_reference;
1704  i--;
1705  j--;
1706  }
1707  else if (tb_mat[i][j] == 'U')
1708  {
1709  aligned_query = query[i] + aligned_query;
1710  aligned_reference = "_" + aligned_reference;
1711  i--;
1712  }
1713  else if (tb_mat[i][j] == 'L')
1714  {
1715  aligned_query = "_" + aligned_query;
1716  aligned_reference = reference[j] + aligned_reference;
1717  j--;
1718  }
1719  else
1720  {
1721  cout << "ERROR: Invalid traceback matrix value" << endl;
1722  break;
1723  }
1724  }
1725 
1726  // Finish up the rest of the characters in the query and reference
1727  while (i >= 0)
1728  {
1729  aligned_query = query[i] + aligned_query;
1730  aligned_reference = "_" + aligned_reference;
1731  i--;
1732  }
1733  while (j >= 0)
1734  {
1735  aligned_query = "_" + aligned_query;
1736  aligned_reference = reference[j] + aligned_reference;
1737  j--;
1738  }
1739 
1740  alignments["query"] = aligned_query;
1741  alignments["reference"] = aligned_reference;
1742 }
1743 
1744 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS>
1745 void local_two_piece_affine_solution(std::string query, std::string reference, PENALTY_T &penalties,
1746  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
1747  array<array<string, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
1748  map<string, string> &alignments)
1749 {
1750  const int N_LAYERS_GA = 5; // N_Layers for two piece affine kernel
1751 
1752  // Layer 0: Insertion Matrix
1753  // Layer 1: Match Mismatch Matrix
1754  // Layer 2: Deletion Matrix
1755  // Layer 3: Long Insertion Matrix
1756  // Layer 4: Long Deletion Matrix
1757 
1758  // Declare initial column and row scores
1759  array<array<float, N_LAYERS_GA>, SOL_MAX_QUERY_LENGTH> initial_col;
1760  array<array<float, N_LAYERS_GA>, SOL_MAX_REFERENCE_LENGTH> initial_row;
1761 
1762  float maximum_score = -std::numeric_limits<float>::infinity();
1763  int max_i = 0;
1764  int max_j = 0;
1765 
1766  // Initialize intial column and row values
1767  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1768  {
1769  initial_col[i][0] = -std::numeric_limits<float>::infinity();
1770  initial_col[i][1] = 0;
1771  initial_col[i][2] = -std::numeric_limits<float>::infinity(); // This can be whatever, since won't be accessed
1772  initial_col[i][3] = -std::numeric_limits<float>::infinity();
1773  initial_col[i][4] = -std::numeric_limits<float>::infinity();
1774  }
1775 
1776  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1777  {
1778  initial_row[j][0] = -std::numeric_limits<float>::infinity(); // This can be whatever, since won't be accessed
1779  initial_row[j][1] = 0;
1780  initial_row[j][2] = -std::numeric_limits<float>::infinity();
1781  initial_row[j][3] = -std::numeric_limits<float>::infinity();
1782  initial_row[j][4] = -std::numeric_limits<float>::infinity();
1783  }
1784 
1785  // Initialize the score matrix
1786  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1787  {
1788  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1789  {
1790  for (int k = 0; k < N_LAYERS_GA; k++)
1791  {
1792  score_mat[k][i][j] = 0;
1793  }
1794  }
1795  }
1796 
1797  // Initialize the traceback matrix
1798  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
1799  {
1800  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
1801  {
1802  tb_mat[i][j] = '*';
1803  }
1804  }
1805 
1806  // Fill in the DP matrix and traceback matrix
1807  for (int i = 0; i < query.length(); i++)
1808  {
1809  float del_scr, ins_scr, long_del_scr, long_ins_scr;
1810  float scr_diag, scr_up, scr_left;
1811  for (int j = 0; j < reference.length(); j++)
1812  {
1813  if (i == 0 && j == 0)
1814  {
1815  scr_diag = 0;
1816  scr_up = initial_row[j][1];
1817  scr_left = initial_col[i][1];
1818 
1819  ins_scr = initial_col[i][0];
1820  del_scr = initial_row[j][2];
1821  long_ins_scr = initial_col[i][3];
1822  long_del_scr = initial_row[j][4];
1823  }
1824  else if (i == 0 && j > 0)
1825  {
1826  scr_diag = initial_row[j - 1][1];
1827  scr_up = initial_row[j][1];
1828  scr_left = score_mat[1][i][j - 1];
1829 
1830  ins_scr = score_mat[0][i][j - 1];
1831  del_scr = initial_row[j][2];
1832  long_ins_scr = score_mat[3][i][j - 1];
1833  long_del_scr = initial_row[j][4];
1834  }
1835  else if (i > 0 && j == 0)
1836  {
1837  scr_diag = initial_col[i - 1][1];
1838  scr_up = score_mat[1][i - 1][j];
1839  scr_left = initial_col[i][1];
1840 
1841  ins_scr = initial_col[i][0];
1842  del_scr = score_mat[2][i - 1][j];
1843  long_ins_scr = initial_col[i][3];
1844  long_del_scr = score_mat[4][i - 1][j];
1845  }
1846  else
1847  {
1848  scr_diag = score_mat[1][i - 1][j - 1];
1849  scr_up = score_mat[1][i - 1][j];
1850  scr_left = score_mat[1][i][j - 1];
1851 
1852  ins_scr = score_mat[0][i][j - 1];
1853  del_scr = score_mat[2][i - 1][j];
1854  long_ins_scr = score_mat[3][i][j - 1];
1855  long_del_scr = score_mat[4][i - 1][j];
1856  }
1857 
1858  float insertion_open_score = scr_left + penalties.open + penalties.extend;
1859  float insertion_extend_score = ins_scr + penalties.extend;
1860 
1861  float deletion_open_score = scr_up + penalties.open + penalties.extend;
1862  float deletion_extend_score = del_scr + penalties.extend;
1863 
1864  // addition of two piece affine matrix scores
1865  float long_insertion_open_score = scr_left + penalties.long_open + penalties.long_extend;
1866  float long_insertion_extend_score = long_ins_scr + penalties.long_extend;
1867 
1868  float long_deletion_open_score = scr_up + penalties.long_open + penalties.long_extend;
1869  float long_deletion_extend_score = long_del_scr + penalties.long_extend;
1870 
1871  float mm_score = scr_diag + (query[i] == reference[j] ? penalties.match : penalties.mismatch);
1872 
1873  float insertion_score = max(insertion_open_score, insertion_extend_score);
1874  float deletion_score = max(deletion_open_score, deletion_extend_score);
1875 
1876  float long_insertion_score = max(long_insertion_open_score, long_insertion_extend_score);
1877  float long_deletion_score = max(long_deletion_open_score, long_deletion_extend_score);
1878 
1879  float final_score = max(mm_score, max(max(insertion_score, deletion_score), max(long_insertion_score, long_deletion_score)));
1880 
1881  if (final_score > maximum_score)
1882  {
1883  maximum_score = final_score;
1884  max_i = i;
1885  max_j = j;
1886  }
1887 
1888  score_mat[0][i][j] = insertion_score;
1889  score_mat[1][i][j] = mm_score;
1890  score_mat[2][i][j] = deletion_score;
1891  score_mat[3][i][j] = long_insertion_score;
1892  score_mat[4][i][j] = long_deletion_score;
1893 
1894  // // Choose the maximum score and update the traceback matrix
1895  // if (final_score == mm_score)
1896  // {
1897  // tb_mat[i][j] = "D "; // 'D' indicates a diagonal direction (match or mismatch)
1898  // }
1899  // else if (final_score == deletion_score)
1900  // {
1901  // tb_mat[i][j] = deletion_score == deletion_open_score ? "U " : "UE"; // 'U' indicates an up direction (deletion)
1902  // }
1903  // else if (final_score == insertion_score)
1904  // {
1905  // tb_mat[i][j] = insertion_score == insertion_open_score ? "L " : "LE"; // 'L' indicates a left direction (insertion)
1906  // }
1907  // else if (final_score == long_deletion_score)
1908  // {
1909  // tb_mat[i][j] = long_deletion_score == long_deletion_open_score ? "U " : "UE";
1910  // }
1911  // else if (final_score == long_insertion_score)
1912  // {
1913  // tb_mat[i][j] = long_insertion_score == long_insertion_score ? "L " : "LE";
1914  // }
1915  // else
1916  // {
1917  // cout << "ERROR: Invalid traceback matrix value" << endl;
1918  // break;
1919  // }
1920  }
1921  }
1922 
1923  // Traceback to find the aligned sequences
1924  int i = max_i;
1925  int j = max_j;
1926  string aligned_query = "";
1927  string aligned_reference = "";
1928  int matrix_type = 1;
1929  while (i > 0 && j > 0)
1930  {
1931  switch (matrix_type)
1932  {
1933  // insertion type 1
1934  case 0:
1935  aligned_query = "_" + aligned_query;
1936  aligned_reference = reference[j] + aligned_reference;
1937  if (score_mat[0][i][j] != score_mat[0][i][j - 1] + penalties.extend)
1938  {
1939  matrix_type = 1;
1940  }
1941  j--;
1942  break;
1943  // match/mismatch
1944  case 1:
1945  if (score_mat[1][i][j] == score_mat[1][i - 1][j - 1] + penalties.mismatch)
1946  {
1947  aligned_query = query[i] + aligned_query;
1948  aligned_reference = reference[j] + aligned_reference;
1949  i--;
1950  j--;
1951  }
1952  else if (score_mat[1][i][j] == score_mat[4][i][j])
1953  {
1954  aligned_query = query[i] + aligned_query;
1955  aligned_reference = "_" + aligned_reference;
1956  i--;
1957  matrix_type = 4;
1958  }
1959  else if (score_mat[1][i][j] == score_mat[2][i][j])
1960  {
1961  aligned_query = query[i] + aligned_query;
1962  aligned_reference = "_" + aligned_reference;
1963  i--;
1964  matrix_type = 2;
1965  }
1966  else if (score_mat[1][i][j] == score_mat[3][i][j])
1967  {
1968  aligned_query = "_" + aligned_query;
1969  aligned_reference = reference[j] + aligned_reference;
1970  j--;
1971  matrix_type = 3;
1972  }
1973  else if (score_mat[1][i][j] == score_mat[0][i][j])
1974  {
1975  aligned_query = "_" + aligned_query;
1976  aligned_reference = reference[j] + aligned_reference;
1977  j--;
1978  matrix_type = 0;
1979  }
1980  else if (score_mat[1][i][j] == score_mat[1][i - 1][j - 1] + penalties.match)
1981  {
1982  aligned_query = query[i] + aligned_query;
1983  aligned_reference = reference[j] + aligned_reference;
1984  i--;
1985  j--;
1986  }
1987  else
1988  {
1989  cout << "ERROR: invalid traceback value" << endl;
1990  exit(1);
1991  }
1992  break;
1993  // deletion type 1
1994  case 2:
1995  aligned_query = query[i] + aligned_query;
1996  aligned_reference = "_" + aligned_reference;
1997  if (score_mat[2][i][j] != score_mat[2][i - 1][j] + penalties.extend)
1998  {
1999  matrix_type = 1;
2000  }
2001  i--;
2002  break;
2003  // insertion type 2
2004  case 3:
2005  aligned_query = "_" + aligned_query;
2006  aligned_reference = reference[j] + aligned_reference;
2007  if (score_mat[3][i][j] != score_mat[3][i][j - 1])
2008  {
2009  matrix_type = 1;
2010  }
2011  j--;
2012  break;
2013  // deletion type 2
2014  case 4:
2015  aligned_query = query[i] + aligned_query;
2016  aligned_reference = "_" + aligned_reference;
2017  if (score_mat[4][i][j] != score_mat[4][i - 1][j] + penalties.long_extend)
2018  {
2019  matrix_type = 1;
2020  }
2021  i--;
2022  break;
2023  }
2024  // if (tb_mat[i][j] == "D ")
2025  // {
2026  // aligned_query = query[i] + aligned_query;
2027  // aligned_reference = reference[j] + aligned_reference;
2028  // i--;
2029  // j--;
2030  // }
2031  // else if (tb_mat[i][j] == "U ")
2032  // {
2033  // aligned_query = query[i] + aligned_query;
2034  // aligned_reference = "_" + aligned_reference;
2035  // i--;
2036  // }
2037  // else if (tb_mat[i][j] == "UE")
2038  // {
2039  // aligned_query = query[i] + aligned_query;
2040  // aligned_reference = "_" + aligned_reference;
2041  // i--;
2042  // }
2043  // else if (tb_mat[i][j] == "L ")
2044  // {
2045  // aligned_query = "_" + aligned_query;
2046  // aligned_reference = reference[j] + aligned_reference;
2047  // j--;
2048  // }
2049  // else if (tb_mat[i][j] == "LE")
2050  // {
2051  // aligned_query = "_" + aligned_query;
2052  // aligned_reference = reference[j] + aligned_reference;
2053  // j--;
2054  // }
2055  // else
2056  // {
2057  // cout << "ERROR: Invalid traceback matrix value" << endl;
2058  // break;
2059  // }
2060  }
2061 
2062  // Finish up the rest of the characters in the query and reference
2063  while (i >= 0)
2064  {
2065  aligned_query = query[i] + aligned_query;
2066  aligned_reference = "_" + aligned_reference;
2067  i--;
2068  }
2069  while (j >= 0)
2070  {
2071  aligned_query = "_" + aligned_query;
2072  aligned_reference = reference[j] + aligned_reference;
2073  j--;
2074  }
2075 
2076  alignments["query"] = aligned_query;
2077  alignments["reference"] = aligned_reference;
2078 }
2079 
2080 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS>
2081 void global_dtw_solution(std::vector<std::complex<float>> query, std::vector<std::complex<float>> reference, PENALTY_T &penalties,
2082  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
2083  array<array<string, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
2084  map<string, string> &alignments)
2085 {
2086  // Layer 0: Insertion Matrix
2087  // Layer 1: Match Mismatch Matrix
2088  // Layer 2: Deletion Matrix
2089 
2090  // Declare initial column and row scores
2091  array<array<float, SOL_N_LAYERS>, SOL_MAX_QUERY_LENGTH> initial_col;
2092  array<array<float, SOL_N_LAYERS>, SOL_MAX_REFERENCE_LENGTH> initial_row;
2093 
2094  score_mat[0][0][0] = 0;
2095 
2096  string alignment_str = "";
2097 
2098  float linear_gp = 0;
2099 
2100  // Initialize intial column and row values
2101  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
2102  {
2103  // linear_gp += penalties.linear_gap; // since it was declared with type_t then convert back to int.
2104  initial_col[i][0] = std::numeric_limits<float>::infinity();
2105  }
2106  linear_gp = 0;
2107  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
2108  {
2109  // linear_gp += penalties.linear_gap; // since it was declared with type_t then convert back to int.
2110  initial_row[j][0] = std::numeric_limits<float>::infinity();; // This can be whatever, since won't be accessed
2111  }
2112 
2113  // Initialize the score matrix
2114  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
2115  {
2116  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
2117  {
2118  for (int k = 0; k < SOL_N_LAYERS; k++)
2119  {
2120  score_mat[k][i][j] = 0;
2121  }
2122  }
2123  }
2124 
2125  // Initialize the traceback matrix
2126  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
2127  {
2128  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
2129  {
2130  tb_mat[i][j] = '*';
2131  }
2132  }
2133 
2134  // Fill in the DP matrix and traceback matrix
2135  for (int i = 0; i < query.size(); i++)
2136  {
2137  float scr_diag, scr_up, scr_left;
2138  for (int j = 0; j < reference.size(); j++)
2139  {
2140  if (i == 0 && j == 0)
2141  {
2142  scr_diag = 0;
2143  scr_up = initial_row[j][0];
2144  scr_left = initial_col[i][0];
2145  }
2146  else if (i == 0 && j > 0)
2147  {
2148  scr_diag = initial_row[j - 1][0];
2149  scr_up = initial_row[j][0];
2150  scr_left = score_mat[0][i][j - 1];
2151  }
2152  else if (i > 0 && j == 0)
2153  {
2154  scr_diag = initial_col[i - 1][0];
2155  scr_up = score_mat[0][i - 1][j];
2156  scr_left = initial_col[i][0];
2157  }
2158  else
2159  {
2160  scr_diag = score_mat[0][i - 1][j - 1];
2161  scr_up = score_mat[0][i - 1][j];
2162  scr_left = score_mat[0][i][j - 1];
2163  }
2164 
2165  auto c1 = query[i];
2166  auto c2 = reference[j];
2167  float r1 = c1.real();
2168  float i1 = c1.imag();
2169  float r2 = c2.real();
2170  float i2 = c2.imag();
2171  float dist_img = (i1 - i2) * (i1 - i2);
2172  float dist_real = (r1 - r2) * (r1 - r2);
2173  float dist = dist_img + dist_real;
2174 
2175  // find the minimum
2176  float min_score = scr_up;
2177  tb_mat[i][j] = "U ";
2178  if (scr_diag < min_score)
2179  {
2180  tb_mat[i][j] = "D ";
2181  min_score = scr_diag;
2182  }
2183  if (scr_left < min_score)
2184  {
2185  tb_mat[i][j] = "L ";
2186  min_score = scr_left;
2187  }
2188  score_mat[0][i][j] = dist + min_score;
2189  }
2190  }
2191 
2192  // Traceback to find the aligned sequences
2193  int i = query.size() - 1;
2194  int j = reference.size() - 1;
2195 
2196  // string aligned_query = "";
2197  // string aligned_reference = "";
2198  while (i >= 0 && j >= 0)
2199  {
2200  if (tb_mat[i][j] == "D ")
2201  {
2202  // aligned_query = query[i] + aligned_query;
2203  // aligned_reference = reference[j] + aligned_reference;
2204  alignment_str = "D " + alignment_str;
2205  i--;
2206  j--;
2207  }
2208  else if (tb_mat[i][j] == "U ")
2209  {
2210  // aligned_query = query[i] + aligned_query;
2211  // aligned_reference = "_" + aligned_reference;
2212  alignment_str = "U " + alignment_str;
2213  i--;
2214  }
2215  else if (tb_mat[i][j] == "L ")
2216  {
2217  // aligned_query = "_" + aligned_query;
2218  // aligned_reference = reference[j] + aligned_reference;
2219  alignment_str = "L " + alignment_str;
2220  j--;
2221  }
2222  else if (tb_mat[i][j] == "*")
2223  {
2224  alignment_str = "* " + alignment_str;
2225  i--;
2226  j--;
2227  break;
2228  }
2229  else
2230  {
2231  cout << "ERROR: Invalid traceback matrix value" << endl;
2232  break;
2233  }
2234  }
2235 
2236  // Finish up the rest of the characters in the query and reference
2237  while (i >= 0)
2238  {
2239  // aligned_query = query[i] + aligned_query;
2240  // aligned_reference = "_" + aligned_reference;
2241  i--;
2242  }
2243  while (j >= 0)
2244  {
2245  // aligned_query = "_" + aligned_query;
2246  // aligned_reference = reference[j] + aligned_reference;
2247  j--;
2248  }
2249 
2250  // alignments["query"] = aligned_query;
2251  // alignments["reference"] = aligned_reference;
2252  alignments["traceback_pointers"] = alignment_str;
2253 }
2254 
2255 template <typename PENALTY_T, int SOL_MAX_QUERY_LENGTH, int SOL_MAX_REFERENCE_LENGTH, int SOL_N_LAYERS>
2256 void global_two_piece_affine_solution(std::string query, std::string reference, PENALTY_T &penalties,
2257  array<array<array<float, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH>, SOL_N_LAYERS> &score_mat,
2258  array<array<string, SOL_MAX_REFERENCE_LENGTH>, SOL_MAX_QUERY_LENGTH> &tb_mat,
2259  map<string, string> &alignments)
2260 {
2261  const int N_LAYERS_GA = 5; // N_Layers for two piece affine kernel
2262 
2263  // Layer 0: Insertion Matrix
2264  // Layer 1: Match Mismatch Matrix
2265  // Layer 2: Deletion Matrix
2266  // Layer 3: Long Insertion Matrix
2267  // Layer 4: Longer Delection Matrix
2268 
2269  // Declare initial column and row scores
2270  array<array<float, N_LAYERS_GA>, SOL_MAX_QUERY_LENGTH> initial_col;
2271  array<array<float, N_LAYERS_GA>, SOL_MAX_REFERENCE_LENGTH> initial_row;
2272 
2273  // initial_col[0][0] = -std::numeric_limits<float>::infinity();
2274  // initial_col[0][1] = 0;
2275  // initial_col[0][2] = -std::numeric_limits<float>::infinity();
2276  // initial_col[0][3] = -std::numeric_limits<float>::infinity();
2277  // initial_col[0][4] = -std::numeric_limits<float>::infinity();
2278 
2279  // initial_row[0][0] = -std::numeric_limits<float>::infinity();
2280  // initial_row[0][1] = 0;
2281  // initial_row[0][2] = -std::numeric_limits<float>::infinity();
2282  // initial_row[0][3] = -std::numeric_limits<float>::infinity();
2283  // initial_row[0][4] = -std::numeric_limits<float>::infinity();
2284 
2285  // Initialize intial column and row values
2286  float short_pen = penalties.open;
2287  float long_pen = penalties.long_open;
2288  for (int j = 0; j < SOL_MAX_QUERY_LENGTH; j++)
2289  {
2290  short_pen += penalties.extend;
2291  long_pen += penalties.long_extend;
2292  initial_col[j][0] = -std::numeric_limits<float>::infinity();
2293  initial_col[j][2] = -std::numeric_limits<float>::infinity();
2294  initial_col[j][3] = -std::numeric_limits<float>::infinity();
2295  initial_col[j][4] = -std::numeric_limits<float>::infinity();
2296  initial_col[j][1] = short_pen > long_pen ? short_pen : long_pen;
2297  }
2298  short_pen = penalties.open;
2299  long_pen = penalties.long_open;
2300  for (int i = 0; i < SOL_MAX_REFERENCE_LENGTH; i++)
2301  {
2302  short_pen += penalties.extend;
2303  long_pen += penalties.long_extend;
2304  initial_row[i][0] = -std::numeric_limits<float>::infinity();
2305  initial_row[i][2] = -std::numeric_limits<float>::infinity();
2306  initial_row[i][3] = -std::numeric_limits<float>::infinity();
2307  initial_row[i][4] = -std::numeric_limits<float>::infinity();
2308  initial_row[i][1] = long_pen > short_pen ? long_pen : short_pen;
2309  }
2310 
2311  // Initialize the score matrix
2312  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
2313  {
2314  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
2315  {
2316  for (int k = 0; k < N_LAYERS_GA; k++)
2317  {
2318  score_mat[k][i][j] = 0;
2319  }
2320  }
2321  }
2322 
2323  // Initialize the traceback matrix
2324  for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++)
2325  {
2326  for (int j = 0; j < SOL_MAX_REFERENCE_LENGTH; j++)
2327  {
2328  tb_mat[i][j] = '*';
2329  }
2330  }
2331 
2332  // Fill in the DP matrix and traceback matrix
2333  for (int i = 0; i < query.length(); i++)
2334  {
2335  float del_scr, ins_scr, long_del_scr, long_ins_scr;
2336  float scr_diag, scr_up, scr_left;
2337  for (int j = 0; j < reference.length(); j++)
2338  {
2339  if (i == 0 && j == 0)
2340  {
2341  scr_diag = 0;
2342  scr_up = initial_row[j][1];
2343  scr_left = initial_col[i][1];
2344 
2345  ins_scr = initial_col[i][0];
2346  del_scr = initial_row[j][2];
2347  long_ins_scr = initial_col[i][3];
2348  long_del_scr = initial_row[j][4];
2349  }
2350  else if (i == 0 && j > 0)
2351  {
2352  scr_diag = initial_row[j - 1][1];
2353  scr_up = initial_row[j][1];
2354  scr_left = score_mat[1][i][j - 1];
2355 
2356  ins_scr = score_mat[0][i][j - 1];
2357  del_scr = initial_row[j][2];
2358  long_ins_scr = score_mat[3][i][j - 1];
2359  long_del_scr = initial_row[j][4];
2360  }
2361  else if (i > 0 && j == 0)
2362  {
2363  scr_diag = initial_col[i - 1][1];
2364  scr_up = score_mat[1][i - 1][j];
2365  scr_left = initial_col[i][1];
2366 
2367  ins_scr = initial_col[i][0];
2368  del_scr = score_mat[2][i - 1][j];
2369  long_ins_scr = initial_col[i][3];
2370  long_del_scr = score_mat[4][i - 1][j];
2371  }
2372  else
2373  {
2374  scr_diag = score_mat[1][i - 1][j - 1];
2375  scr_up = score_mat[1][i - 1][j];
2376  scr_left = score_mat[1][i][j - 1];
2377 
2378  ins_scr = score_mat[0][i][j - 1];
2379  del_scr = score_mat[2][i - 1][j];
2380  long_ins_scr = score_mat[3][i][j - 1];
2381  long_del_scr = score_mat[4][i - 1][j];
2382  }
2383 
2384  float insertion_open_score = scr_left + penalties.open + penalties.extend;
2385  float insertion_extend_score = ins_scr + penalties.extend;
2386 
2387  float deletion_open_score = scr_up + penalties.open + penalties.extend;
2388  float deletion_extend_score = del_scr + penalties.extend;
2389 
2390  // addition of two piece affine matrix scores
2391  float long_insertion_open_score = scr_left + penalties.long_open + penalties.long_extend;
2392  float long_insertion_extend_score = long_ins_scr + penalties.long_extend;
2393 
2394  float long_deletion_open_score = scr_up + penalties.long_open + penalties.long_extend;
2395  float long_deletion_extend_score = long_del_scr + penalties.long_extend;
2396 
2397  float mm_score = scr_diag + (query[i] == reference[j] ? penalties.match : penalties.mismatch);
2398 
2399  float insertion_score = max(insertion_open_score, insertion_extend_score);
2400  float deletion_score = max(deletion_open_score, deletion_extend_score);
2401 
2402  float long_insertion_score = long_insertion_open_score > long_insertion_extend_score ? long_insertion_open_score : long_insertion_extend_score;
2403  float long_deletion_score = long_deletion_open_score > long_deletion_extend_score ? long_deletion_open_score : long_deletion_extend_score;
2404 
2405  float final_score = mm_score;
2406  final_score = final_score > insertion_score ? final_score : insertion_score;
2407  final_score = final_score > deletion_score ? final_score : deletion_score;
2408  final_score = final_score > long_insertion_score ? final_score : long_insertion_score;
2409  final_score = final_score > long_deletion_score ? final_score : long_deletion_score;
2410 
2411  score_mat[0][i][j] = insertion_score;
2412  score_mat[1][i][j] = final_score;
2413  score_mat[2][i][j] = deletion_score;
2414  score_mat[3][i][j] = long_insertion_score;
2415  score_mat[4][i][j] = long_deletion_score;
2416 
2417  // // Choose the maximum score and update the traceback matrix
2418  // if (final_score == mm_score)
2419  // {
2420  // tb_mat[i][j] = "D "; // 'D' indicates a diagonal direction (match or mismatch)
2421  // }
2422  // else if (final_score == deletion_score)
2423  // {
2424  // tb_mat[i][j] = deletion_score == deletion_open_score ? "U " : "UE"; // 'U' indicates an up direction (deletion)
2425  // }
2426  // else if (final_score == insertion_score)
2427  // {
2428  // tb_mat[i][j] = insertion_score == insertion_open_score ? "L " : "LE"; // 'L' indicates a left direction (insertion)
2429  // }
2430  // else if (final_score == long_deletion_score)
2431  // {
2432  // tb_mat[i][j] = long_deletion_score == long_deletion_open_score ? "U " : "UE";
2433  // }
2434  // else if (final_score == long_insertion_score)
2435  // {
2436  // tb_mat[i][j] = long_insertion_score == long_insertion_score ? "L " : "LE";
2437  // }
2438  // else
2439  // {
2440  // cout << "ERROR: Invalid traceback matrix value" << endl;
2441  // break;
2442  // }
2443  }
2444  }
2445 
2446  // Traceback to find the aligned sequences
2447  int i = query.length() - 1;
2448  int j = reference.length() - 1;
2449  string aligned_query = "";
2450  string aligned_reference = "";
2451  int matrix_type = 1;
2452  while (i > 0 && j > 0)
2453  {
2454  switch (matrix_type)
2455  {
2456  case 1:
2457  if (score_mat[1][i][j] == score_mat[1][i - 1][j - 1] + penalties.match)
2458  {
2459  aligned_query = query[i] + aligned_query;
2460  aligned_reference = reference[j] + aligned_reference;
2461  i--;
2462  j--;
2463  }
2464  else if (score_mat[1][i][j] == score_mat[3][i][j])
2465  {
2466  aligned_query = "_" + aligned_query;
2467  aligned_reference = reference[j] + aligned_reference;
2468  j--;
2469  matrix_type = 3;
2470  }
2471  else if (score_mat[1][i][j] == score_mat[4][i][j])
2472  {
2473  aligned_query = query[i] + aligned_query;
2474  aligned_reference = "_" + aligned_reference;
2475  i--;
2476  matrix_type = 4;
2477  }
2478  else if (score_mat[1][i][j] == score_mat[0][i][j])
2479  {
2480  aligned_query = "_" + aligned_query;
2481  aligned_reference = reference[j] + aligned_reference;
2482  j--;
2483  matrix_type = 0;
2484  }
2485  else if (score_mat[1][i][j] == score_mat[2][i][j])
2486  {
2487  aligned_query = query[i] + aligned_query;
2488  aligned_reference = "_" + aligned_reference;
2489  i--;
2490  matrix_type = 2;
2491  }
2492  else if (score_mat[1][i][j] == score_mat[1][i - 1][j - 1] + penalties.mismatch)
2493  {
2494  aligned_query = query[i] + aligned_query;
2495  aligned_reference = reference[j] + aligned_reference;
2496  i--;
2497  j--;
2498  }
2499  else
2500  {
2501  cout << "ERROR: invalid traceback value" << endl;
2502  exit(1);
2503  }
2504  break;
2505  case 3:
2506  aligned_query = "_" + aligned_query;
2507  aligned_reference = reference[j] + aligned_reference;
2508  if (score_mat[3][i][j] != score_mat[3][i][j - 1])
2509  {
2510  matrix_type = 1;
2511  }
2512  j--;
2513  break;
2514  // deletion type 2
2515  case 4:
2516  aligned_query = query[i] + aligned_query;
2517  aligned_reference = "_" + aligned_reference;
2518  if (score_mat[4][i][j] != score_mat[4][i - 1][j] + penalties.long_extend)
2519  {
2520  matrix_type = 1;
2521  }
2522  i--;
2523  break;
2524  case 0:
2525  aligned_query = "_" + aligned_query;
2526  aligned_reference = reference[j] + aligned_reference;
2527  if (score_mat[0][i][j] != score_mat[0][i][j - 1] + penalties.extend)
2528  {
2529  matrix_type = 1;
2530  }
2531  j--;
2532  break;
2533  // deletion type 1
2534  case 2:
2535  aligned_query = query[i] + aligned_query;
2536  aligned_reference = "_" + aligned_reference;
2537  if (score_mat[2][i][j] != score_mat[2][i - 1][j] + penalties.extend)
2538  {
2539  matrix_type = 1;
2540  }
2541  i--;
2542  break;
2543  }
2544  // if (tb_mat[i][j] == "D ")
2545  // {
2546  // aligned_query = query[i] + aligned_query;
2547  // aligned_reference = reference[j] + aligned_reference;
2548  // i--;
2549  // j--;
2550  // }
2551  // else if (tb_mat[i][j] == "U ")
2552  // {
2553  // aligned_query = query[i] + aligned_query;
2554  // aligned_reference = "_" + aligned_reference;
2555  // i--;
2556  // }
2557  // else if (tb_mat[i][j] == "UE")
2558  // {
2559  // aligned_query = query[i] + aligned_query;
2560  // aligned_reference = "_" + aligned_reference;
2561  // i--;
2562  // }
2563  // else if (tb_mat[i][j] == "L ")
2564  // {
2565  // aligned_query = "_" + aligned_query;
2566  // aligned_reference = reference[j] + aligned_reference;
2567  // j--;
2568  // }
2569  // else if (tb_mat[i][j] == "LE")
2570  // {
2571  // aligned_query = "_" + aligned_query;
2572  // aligned_reference = reference[j] + aligned_reference;
2573  // j--;
2574  // }
2575  // else
2576  // {
2577  // cout << "ERROR: Invalid traceback matrix value" << endl;
2578  // break;
2579  // }
2580  }
2581 
2582  // Finish up the rest of the characters in the query and reference
2583  while (i >= 0)
2584  {
2585  aligned_query = query[i] + aligned_query;
2586  aligned_reference = "_" + aligned_reference;
2587  i--;
2588  }
2589  while (j >= 0)
2590  {
2591  aligned_query = "_" + aligned_query;
2592  aligned_reference = reference[j] + aligned_reference;
2593  j--;
2594  }
2595 
2596  alignments["query"] = aligned_query;
2597  alignments["reference"] = aligned_reference;
2598 }
2599 
2600 template <typename T, int M, int N>
2601 void print_matrix(array<array<T, N>, M> &mat, string name, std::set<std::tuple<int, int, int>> incorrect_coordinates, int layer_k)
2602 {
2603  int width = 2;
2604  cout << name << endl;
2605  for (int i = 0; i < M; i++)
2606  {
2607  for (int j = 0; j < N; j++)
2608  {
2609  std::tuple<int, int, int> search_tuple = std::make_tuple(layer_k, i, j);
2610  bool wrong_score = incorrect_coordinates.find(search_tuple) != incorrect_coordinates.end();
2611  if (wrong_score) std::cout << "\033[31m";
2612 
2613  cout << std::right << std::setw(width) << mat[i][j] << " ";
2614 
2615  if (wrong_score) std::cout << "\033[0m";
2616  }
2617  cout << endl;
2618  }
2619 }
2620 
2621 template <typename T, int M, int N>
2622 void fprint_matrix(ofstream &file, array<array<T, N>, M> &mat, string name)
2623 {
2624  int width = 2;
2625  file << name << endl;
2626  for (int i = 0; i < M; i++)
2627  {
2628  for (int j = 0; j < N; j++)
2629  {
2630  file << std::right << std::setw(width) << mat[i][j] << " ";
2631  }
2632  file << endl;
2633  }
2634 }
2635 
2636 template <typename T, int M, int N>
2637 void fprint_matrix(ofstream &file, array<array<T, N>, M> &mat, string query, string reference, string name)
2638 {
2639  int width = 3;
2640  file << name << endl;
2641  file << std::right << std::setw(width) << " ";
2642  file << std::right << std::setw(width) << " ";
2643  // print some index in the first row
2644  for (int j = 0; j < N; j++)
2645  {
2646  file << " " << std::right << std::setw(width) << j;
2647  }
2648  file << endl;
2649  file << std::right << std::setw(width) << " ";
2650  file << std::right << std::setw(width) << " ";
2651  for (int j = 0; j < N; j++)
2652  {
2653  file << " " << std::right << std::setw(width) << (j < reference.length() ? reference[j] : ' ');
2654  }
2655  file << endl;
2656  for (int i = 0; i < M; i++)
2657  {
2658  file << std::right << std::setw(width) << i << " ";
2659  file << std::right << std::setw(width) << (i < query.length() ? query[i] : ' ') << " ";
2660  for (int j = 0; j < N; j++)
2661  {
2662  file << std::right << std::setw(width) << mat[i][j] << " ";
2663  }
2664  file << endl;
2665  }
2666 }
2667 
2668 template <typename T, int N>
2669 void print_vector(array<T, N> &vec, string name)
2670 {
2671  cout << name << endl;
2672  for (int i = 0; i < N; i++)
2673  {
2674  cout << vec[i] << " ";
2675  }
2676  cout << endl;
2677 }
void profile_alignment_solution(std::vector< std::array< int, 5 >> query, std::vector< std::array< int, 5 >> reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< char, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, std::vector< char > &alignments)
Definition: solutions.h:38
void local_affine_solution(std::string query, std::string reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< string, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, map< string, string > &alignments)
Definition: solutions.h:850
void global_affine_solution(std::string query, std::string reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< string, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, map< string, string > &alignments)
Definition: solutions.h:475
float score_mult(const std::array< int, ALPHABET_SIZE > &query, const std::array< int, ALPHABET_SIZE > &reference, const std::array< std::array< float, ALPHABET_SIZE >, ALPHABET_SIZE > &A)
Definition: solutions.h:21
void global_two_piece_affine_solution(std::string query, std::string reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< string, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, map< string, string > &alignments)
Definition: solutions.h:2256
void overlap_linear_prefix_suffix_solution(std::string query, std::string reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< char, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, map< string, string > &alignments)
Definition: solutions.h:1413
void semi_global_linear_short_long_solution(std::string query, std::string reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< char, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, map< string, string > &alignments)
Definition: solutions.h:1244
void semi_global_linear_long_short_solution(std::string query, std::string reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< char, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, map< string, string > &alignments)
Definition: solutions.h:1075
void print_vector(array< T, N > &vec, string name)
Definition: solutions.h:2669
void local_linear_solution(std::string query, std::string reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< char, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, map< string, string > &alignments)
Definition: solutions.h:675
void fprint_matrix(ofstream &file, array< array< T, N >, M > &mat, string name)
Definition: solutions.h:2622
void global_dtw_solution(std::vector< std::complex< float >> query, std::vector< std::complex< float >> reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< string, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, map< string, string > &alignments)
Definition: solutions.h:2081
void local_two_piece_affine_solution(std::string query, std::string reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< string, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, map< string, string > &alignments)
Definition: solutions.h:1745
void fixed_banding_global_linear_solution(std::string query, std::string reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< char, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, map< string, string > &alignments)
Definition: solutions.h:294
void overlap_linear_suffix_prefix_solution(std::string query, std::string reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< char, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, map< string, string > &alignments)
Definition: solutions.h:1581
void global_linear_solution(std::string query, std::string reference, PENALTY_T &penalties, array< array< array< float, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH >, SOL_N_LAYERS > &score_mat, array< array< char, SOL_MAX_REFERENCE_LENGTH >, SOL_MAX_QUERY_LENGTH > &tb_mat, map< string, string > &alignments)
Definition: solutions.h:139
void print_matrix(array< array< T, N >, M > &mat, string name, std::set< std::tuple< int, int, int >> incorrect_coordinates, int layer_k)
Definition: solutions.h:2601