44 #include <range/v3/view/slice.hpp> 71 inline std::vector<search_dyn> compute_ss(uint8_t
const min_error, uint8_t
const max_error)
78 std::vector<search_dyn> scheme{{{1}, {min_error}, {max_error}}};
98 template <
typename search_scheme_t>
99 inline auto search_scheme_block_info(search_scheme_t
const & search_scheme,
size_t const query_length)
101 using blocks_length_type =
typename search_scheme_t::value_type::blocks_length_type;
106 using result_type = std::conditional_t<is_dyn_scheme,
107 std::vector<std::tuple<blocks_length_type, size_t>>,
108 std::array<std::tuple<blocks_length_type, size_t>,
110 std::false_type>::value>>;
113 if constexpr (is_dyn_scheme)
114 result.resize(search_scheme.size());
116 uint8_t
const blocks {search_scheme[0].blocks()};
117 size_t const block_length{query_length / blocks};
118 uint8_t
const rest {
static_cast<uint8_t
>(query_length % blocks)};
120 blocks_length_type blocks_length;
123 if constexpr (is_dyn_scheme)
124 blocks_length.resize(blocks, block_length);
126 blocks_length.fill(block_length);
128 for (uint8_t block_id = 0; block_id < rest; ++block_id)
129 ++blocks_length[block_id];
131 for (uint8_t search_id = 0; search_id < search_scheme.size(); ++search_id)
133 auto const &
search = search_scheme[search_id];
135 auto & [search_blocks_length, start_pos] = result[search_id];
139 if constexpr (is_dyn_scheme)
140 search_blocks_length.resize(blocks);
141 search_blocks_length[0] = blocks_length[
search.pi[0] - 1];
142 for (uint8_t i = 1; i < blocks; ++i)
144 search_blocks_length[i] = blocks_length[
search.pi[i] - 1] + search_blocks_length[i - 1];
146 start_pos += search_blocks_length[i] - search_blocks_length[i - 1];
155 template <
bool abort_on_hit,
typename iterator_t,
typename query_t,
typename search_t,
typename blocks_length_t,
157 inline bool search_ss(iterator_t it, query_t & query,
158 typename iterator_t::size_type
const lb,
typename iterator_t::size_type
const rb,
159 uint8_t
const errors_spent, uint8_t
const block_id,
bool const go_right, search_t
const &
search,
160 blocks_length_t
const & blocks_length, search_param
const error_left, delegate_t && delegate);
193 template <
bool abort_on_hit,
typename iterator_t,
typename query_t,
typename search_t,
typename blocks_length_t,
195 inline bool search_ss_exact(iterator_t it, query_t & query,
196 typename iterator_t::size_type
const lb,
typename iterator_t::size_type
const rb,
197 uint8_t
const errors_spent, uint8_t
const block_id,
bool const go_right,
198 search_t
const &
search, blocks_length_t
const & blocks_length,
199 search_param
const error_left, delegate_t && delegate)
201 using size_type =
typename iterator_t::size_type;
203 uint8_t
const block_id2 = std::min<uint8_t>(block_id + 1, search.blocks() - 1);
204 bool const go_right2 = (block_id < search.blocks() - 1) && (search.pi[block_id + 1] > search.pi[block_id]);
208 size_type
const infix_lb = rb - 1;
209 size_type
const infix_rb = lb + blocks_length[block_id] - 1;
211 if (!it.extend_right(query | ranges::view::slice(infix_lb, infix_rb + 1)))
214 if (search_ss<abort_on_hit>(it, query, lb, infix_rb + 2, errors_spent, block_id2, go_right2, search,
215 blocks_length, error_left, delegate) && abort_on_hit)
222 size_type
const infix_lb = rb - blocks_length[block_id] - 1;
223 size_type
const infix_rb = lb - 1;
225 if (!it.extend_left(query | ranges::view::slice(infix_lb, infix_rb + 1)))
228 if (search_ss<abort_on_hit>(it, query, infix_lb, rb, errors_spent, block_id2, go_right2, search, blocks_length,
229 error_left, delegate) && abort_on_hit)
242 template <
bool abort_on_hit,
typename iterator_t,
typename query_t,
typename search_t,
typename blocks_length_t,
244 inline bool search_ss_deletion(iterator_t it, query_t & query,
245 typename iterator_t::size_type
const lb,
typename iterator_t::size_type
const rb,
246 uint8_t
const errors_spent, uint8_t
const block_id,
bool const go_right,
247 search_t
const & search, blocks_length_t
const & blocks_length,
248 search_param
const error_left, delegate_t && delegate)
250 uint8_t
const max_error_left_in_block = search.u[block_id] - errors_spent;
251 uint8_t
const min_error_left_in_block = std::max(search.l[block_id] - errors_spent, 0);
254 if (min_error_left_in_block == 0)
256 uint8_t
const block_id2 = std::min<uint8_t>(block_id + 1, search.blocks() - 1);
257 bool const go_right2 = search.pi[block_id2] > search.pi[block_id2 - 1];
259 if (search_ss<abort_on_hit>(it, query, lb, rb, errors_spent, block_id2, go_right2, search, blocks_length,
260 error_left, delegate) && abort_on_hit)
269 if (!(search.pi[block_id] == 1 && !go_right) &&
270 !(search.pi[block_id] == search.blocks() && go_right) &&
271 max_error_left_in_block > 0 && error_left.total > 0 && error_left.deletion > 0 &&
272 ((go_right && it.extend_right()) || (!go_right && it.extend_left())))
274 search_param error_left2{error_left};
276 error_left2.deletion--;
279 if (search_ss_deletion<abort_on_hit>(it, query, lb, rb, errors_spent + 1, block_id, go_right, search,
280 blocks_length, error_left2, delegate) && abort_on_hit)
284 }
while ((go_right && it.cycle_back()) || (!go_right && it.cycle_front()));
296 template <
bool abort_on_hit,
typename iterator_t,
typename query_t,
typename search_t,
typename blocks_length_t,
298 inline bool search_ss_children(iterator_t it, query_t & query,
299 typename iterator_t::size_type
const lb,
typename iterator_t::size_type
const rb,
300 uint8_t
const errors_spent, uint8_t
const block_id,
bool const go_right,
301 uint8_t
const min_error_left_in_block, search_t
const & search,
302 blocks_length_t
const & blocks_length, search_param
const error_left,
303 delegate_t && delegate)
305 using size_type =
typename iterator_t::size_type;
306 if ((go_right && it.extend_right()) || (!go_right && it.extend_left()))
308 size_type
const chars_left = blocks_length[block_id] - (rb - lb - 1);
310 size_type lb2 = lb - !go_right;
311 size_type rb2 = rb + go_right;
315 bool const delta = it.last_char() != query[(go_right ? rb : lb) - 1];
321 if (error_left.deletion == 0 && chars_left + delta < min_error_left_in_block + 1u)
324 if (!delta || error_left.substitution > 0)
326 search_param error_left2{error_left};
327 error_left2.total -= delta;
328 error_left2.substitution -= delta;
331 if (rb - lb == blocks_length[block_id])
335 if (error_left.deletion > 0)
337 if (search_ss_deletion<abort_on_hit>(it, query, lb2, rb2, errors_spent + delta, block_id,
338 go_right, search, blocks_length, error_left2, delegate) &&
346 uint8_t
const block_id2 = std::min<uint8_t>(block_id + 1, search.blocks() - 1);
347 bool const go_right2 = search.pi[block_id2] > search.pi[block_id2 - 1];
349 if (search_ss<abort_on_hit>(it, query, lb2, rb2, errors_spent + delta, block_id2, go_right2,
350 search, blocks_length, error_left2, delegate) &&
359 if (search_ss<abort_on_hit>(it, query, lb2, rb2, errors_spent + delta, block_id, go_right, search,
360 blocks_length, error_left2, delegate) && abort_on_hit)
371 if (error_left.deletion > 0 &&
372 !(go_right && (rb == 1 || rb == query.size() + 1)) &&
373 !(!go_right && (lb == 0 || lb == query.size())))
375 search_param error_left3{error_left};
377 error_left3.deletion--;
378 search_ss<abort_on_hit>(it, query, lb, rb, errors_spent + 1, block_id, go_right,
search, blocks_length,
379 error_left3, delegate);
381 }
while ((go_right && it.cycle_back()) || (!go_right && it.cycle_front()));
390 template <
bool abort_on_hit,
typename iterator_t,
typename query_t,
typename search_t,
391 typename blocks_length_t,
typename delegate_t>
392 inline bool search_ss(iterator_t it, query_t & query,
393 typename iterator_t::size_type
const lb,
typename iterator_t::size_type
const rb,
394 uint8_t
const errors_spent, uint8_t
const block_id,
bool const go_right, search_t
const & search,
395 blocks_length_t
const & blocks_length, search_param
const error_left, delegate_t && delegate)
397 uint8_t
const max_error_left_in_block = search.u[block_id] - errors_spent;
398 uint8_t
const min_error_left_in_block = std::max(search.l[block_id] - errors_spent, 0);
401 if (min_error_left_in_block == 0 && lb == 0 && rb == query.size() + 1)
407 else if (((max_error_left_in_block == 0) && (rb - lb - 1 != blocks_length[block_id])) ||
408 (error_left.total == 0 && min_error_left_in_block == 0))
410 if (search_ss_exact<abort_on_hit>(it, query, lb, rb, errors_spent, block_id, go_right, search, blocks_length,
411 error_left, delegate) && abort_on_hit)
418 else if (error_left.total > 0)
421 if (error_left.insertion > 0)
423 using size_type =
typename iterator_t::size_type;
425 size_type
const lb2 = lb - !go_right;
426 size_type
const rb2 = rb + go_right;
428 search_param error_left2{error_left};
430 error_left2.insertion--;
432 if (rb - lb == blocks_length[block_id])
439 if (search_ss_deletion<abort_on_hit>(it, query, lb2, rb2, errors_spent + 1, block_id, go_right, search,
440 blocks_length, error_left2, delegate) && abort_on_hit)
447 if (search_ss<abort_on_hit>(it, query, lb2, rb2, errors_spent + 1, block_id, go_right, search,
448 blocks_length, error_left2, delegate) && abort_on_hit)
454 if (search_ss_children<abort_on_hit>(it, query, lb, rb, errors_spent, block_id, go_right,
455 min_error_left_in_block, search, blocks_length, error_left, delegate) &&
485 template <
bool abort_on_hit,
typename index_t,
typename query_t,
typename search_scheme_t,
typename delegate_t>
486 inline void search_ss(index_t
const & index, query_t & query, search_param
const error_left,
487 search_scheme_t
const & search_scheme, delegate_t && delegate)
490 auto const block_info = search_scheme_block_info(search_scheme, query.size());
492 for (uint8_t search_id = 0; search_id < search_scheme.size(); ++search_id)
494 auto const & search = search_scheme[search_id];
495 auto const & [blocks_length, start_pos] = block_info[search_id];
497 bool const hit = search_ss<abort_on_hit>(
500 start_pos, start_pos + 1,
510 if (abort_on_hit && hit)
534 template <
bool abort_on_hit,
typename index_t,
typename query_t,
typename delegate_t>
535 inline void search_algo_bi(index_t
const & index, query_t & query, search_param
const error_left,
536 delegate_t && delegate)
538 switch (error_left.total)
541 search_ss<abort_on_hit>(index, query, error_left, optimum_search_scheme<0, 0>, delegate);
544 search_ss<abort_on_hit>(index, query, error_left, optimum_search_scheme<0, 1>, delegate);
547 search_ss<abort_on_hit>(index, query, error_left, optimum_search_scheme<0, 2>, delegate);
550 search_ss<abort_on_hit>(index, query, error_left, optimum_search_scheme<0, 3>, delegate);
553 auto const & search_scheme{compute_ss(0, error_left.total)};
554 search_ss<abort_on_hit>(index, query, error_left, search_scheme, delegate);
563 template <
bool abort_on_hit,
typename index_t,
typename query_t,
typename delegate_t>
564 inline void search_algo_uni(index_t
const & index, query_t & query, search_param
const error_left,
565 delegate_t && delegate)
567 search_trivial<abort_on_hit>(index, query, error_left, delegate);
574 template <
bool abort_on_hit,
typename index_t,
typename query_t,
typename delegate_t>
575 inline void search_algo(index_t
const & index, query_t & query, search_param
const error_left, delegate_t && delegate)
577 if constexpr (bi_fm_index_concept<index_t>)
578 search_algo_bi<abort_on_hit>(index, query, error_left, delegate);
580 search_algo_uni<abort_on_hit>(index, query, error_left, delegate);
Provides the data structures and precomputed instances for (optimum) search schemes.
Provides the concepts for seqan3::fm_index and seqan3::bi_fm_index and its traits and iterators...
auto search(index_t const &index, queries_t &&queries, configuration_t const &cfg)
Search a query or a range of queries in an index.
Definition: search.hpp:82
::ranges::iterator_t iterator_t
Alias for ranges::iterator_t. Obtains the iterator type of a range.
Definition: ranges:225
The concept std::Same<T, U> is satisfied if and only if T and U denote the same type.
Provides an approximate string matching algorithm based on simple backtracking. This should only be u...
Definition: aligned_sequence_concept.hpp:288
Provides C++20 additions to the type_traits header.
Provides data structures used by different search algorithms.