SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
pairwise_alignment_algorithm_banded.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <seqan3/std/concepts>
16 #include <seqan3/std/ranges>
17 
22 
23 namespace seqan3::detail
24 {
25 
31 template <typename alignment_configuration_t, typename ...policies_t>
33  requires is_type_specialisation_of_v<alignment_configuration_t, configuration>
35 class pairwise_alignment_algorithm_banded :
36  protected pairwise_alignment_algorithm<alignment_configuration_t, policies_t...>
37 {
38 protected:
40  using base_algorithm_t = pairwise_alignment_algorithm<alignment_configuration_t, policies_t...>;
41 
42  // import types from base class.
43  using typename base_algorithm_t::traits_type;
44  using typename base_algorithm_t::alignment_result_type;
45  using typename base_algorithm_t::score_type;
46 
47  static_assert(!std::same_as<alignment_result_type, empty_type>, "Alignment result type was not configured.");
48  static_assert(traits_type::is_banded, "Alignment configuration must have band configured.");
49 
50 public:
54  pairwise_alignment_algorithm_banded() = default;
55  pairwise_alignment_algorithm_banded(pairwise_alignment_algorithm_banded const &) = default;
56  pairwise_alignment_algorithm_banded(pairwise_alignment_algorithm_banded &&) = default;
57  pairwise_alignment_algorithm_banded & operator=(pairwise_alignment_algorithm_banded const &) = default;
58  pairwise_alignment_algorithm_banded & operator=(pairwise_alignment_algorithm_banded &&) = default;
59  ~pairwise_alignment_algorithm_banded() = default;
60 
70  pairwise_alignment_algorithm_banded(alignment_configuration_t const & config) : base_algorithm_t(config)
71  {}
73 
77  template <indexed_sequence_pair_range indexed_sequence_pairs_t, typename callback_t>
80  requires std::invocable<callback_t, alignment_result_type>
82  void operator()(indexed_sequence_pairs_t && indexed_sequence_pairs, callback_t && callback)
83  {
84  using std::get;
85 
86  for (auto && [sequence_pair, idx] : indexed_sequence_pairs)
87  {
88  size_t const sequence1_size = std::ranges::distance(get<0>(sequence_pair));
89  size_t const sequence2_size = std::ranges::distance(get<1>(sequence_pair));
90 
91  auto && [alignment_matrix, index_matrix] = this->acquire_matrices(sequence1_size,
92  sequence2_size,
93  this->lowest_viable_score());
94 
95  compute_matrix(get<0>(sequence_pair), get<1>(sequence_pair), alignment_matrix, index_matrix);
96  this->make_result_and_invoke(std::forward<decltype(sequence_pair)>(sequence_pair),
97  std::move(idx),
98  this->optimal_score,
99  this->optimal_coordinate,
100  callback);
101  }
102  }
104 
105 protected:
158  template <std::ranges::forward_range sequence1_t,
159  std::ranges::forward_range sequence2_t,
160  std::ranges::input_range alignment_matrix_t,
161  std::ranges::input_range index_matrix_t>
163  requires std::ranges::forward_range<std::ranges::range_reference_t<alignment_matrix_t>> &&
164  std::ranges::forward_range<std::ranges::range_reference_t<index_matrix_t>>
166  void compute_matrix(sequence1_t && sequence1,
167  sequence2_t && sequence2,
168  alignment_matrix_t && alignment_matrix,
169  index_matrix_t && index_matrix)
170  {
171  // ---------------------------------------------------------------------
172  // Initialisation phase: allocate memory and initialise first column.
173  // ---------------------------------------------------------------------
174 
175  this->reset_optimum(); // Reset the tracker for the new alignment computation.
176 
177  auto alignment_matrix_it = alignment_matrix.begin();
178  auto indexed_matrix_it = index_matrix.begin();
179 
180  size_t row_size = std::max<int32_t>(0, -this->lower_diagonal);
181  size_t const column_size = std::max<int32_t>(0, this->upper_diagonal);
182  this->initialise_column(*alignment_matrix_it, *indexed_matrix_it, sequence2 | views::take(row_size));
183 
184  // ---------------------------------------------------------------------
185  // 1st recursion phase: band intersects with the first row.
186  // ---------------------------------------------------------------------
187 
188  for (auto sequence1_value : sequence1 | views::take(column_size))
189  {
190  this->compute_column(*++alignment_matrix_it,
191  *++indexed_matrix_it,
192  sequence1_value,
193  sequence2 | views::take(++row_size));
194  }
195 
196  // ---------------------------------------------------------------------
197  // 2nd recursion phase: iterate until the end of the matrix.
198  // ---------------------------------------------------------------------
199 
200  size_t first_row_index = 0u;
201  for (auto sequence1_value : sequence1 | views::drop(column_size))
202  {
203  compute_band_column(*++alignment_matrix_it,
204  *++indexed_matrix_it | views::drop(first_row_index + 1),
205  sequence1_value,
206  sequence2 | views::slice(first_row_index, ++row_size));
207  ++first_row_index;
208  }
209 
210  // ---------------------------------------------------------------------
211  // Final phase: track score of last column
212  // ---------------------------------------------------------------------
213 
214  auto alignment_column = *alignment_matrix_it;
215  auto cell_index_column = *indexed_matrix_it | views::drop(first_row_index);
216 
217  auto alignment_column_it = alignment_column.begin();
218  auto cell_index_column_it = cell_index_column.begin();
219 
220  this->track_last_column_cell(*alignment_column_it, *cell_index_column_it);
221 
222  for (size_t last_row = std::min<size_t>(std::ranges::distance(sequence2), row_size);
223  first_row_index < last_row;
224  ++first_row_index)
225  this->track_last_column_cell(*++alignment_column_it, *++cell_index_column_it);
226 
227  this->track_final_cell(*alignment_column_it, *cell_index_column_it);
228  }
229 
249  template <std::ranges::input_range alignment_column_t,
250  std::ranges::input_range cell_index_column_t,
251  semialphabet sequence1_value_t,
252  std::ranges::input_range sequence2_t>
253  void compute_band_column(alignment_column_t && alignment_column,
254  cell_index_column_t && cell_index_column,
255  sequence1_value_t const & sequence1_value,
256  sequence2_t && sequence2)
257  {
258  // ---------------------------------------------------------------------
259  // Initial phase: prepare column and initialise first cell
260  // ---------------------------------------------------------------------
261 
262  auto alignment_column_it = alignment_column.begin();
263  auto cell_index_column_it = cell_index_column.begin();
264 
265  auto cell = *alignment_column_it;
266  cell = this->track_cell(
267  this->initialise_band_first_cell(cell.best_score(),
268  *++alignment_column_it,
269  this->scoring_scheme.score(sequence1_value,
270  *std::ranges::begin(sequence2))),
271  *cell_index_column_it);
272 
273  // ---------------------------------------------------------------------
274  // Iteration phase: iterate over column and compute each cell
275  // ---------------------------------------------------------------------
276 
277  for (auto && sequence2_value : sequence2 | views::drop(1))
278  {
279  auto cell = *alignment_column_it;
280  cell = this->track_cell(
281  this->compute_inner_cell(cell.best_score(),
282  *++alignment_column_it,
283  this->scoring_scheme.score(sequence1_value, sequence2_value)),
284  *++cell_index_column_it);
285  }
286 
287  // ---------------------------------------------------------------------
288  // Final phase: track last cell
289  // ---------------------------------------------------------------------
290 
291  this->track_last_row_cell(*alignment_column_it, *cell_index_column_it);
292  }
293 };
294 
295 } // namespace seqan3::detail
drop.hpp
Provides seqan3::views::drop.
seqan3::views::get
auto const get
A view calling std::get on each element in a range.
Definition: get.hpp:65
pairwise_alignment_algorithm.hpp
Provides seqan3::detail::pairwise_alignment_algorithm.
concepts
The Concepts library.
slice.hpp
Provides seqan3::views::slice.
seqan3::views::move
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:68
std::forward
T forward(T... args)
seqan3::views::take
constexpr auto take
A view adaptor that returns the first size elements from the underlying range (or less if the underly...
Definition: take.hpp:611
take.hpp
Provides seqan3::views::take.
ranges
Adaptations of concepts from the Ranges TS.
seqan3::views::drop
constexpr auto drop
A view adaptor that returns all elements after n from the underlying range (or an empty range if the ...
Definition: drop.hpp:169
seqan3::views::slice
constexpr auto slice
A view adaptor that returns a half-open interval on the underlying range.
Definition: slice.hpp:141
semialphabet
The basis for seqan3::alphabet, but requires only rank interface (not char).