SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
search_scheme_algorithm.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2024 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2024 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <type_traits>
13
21
22namespace seqan3::detail
23{
24
31template <typename configuration_t, typename index_t, typename... policies_t>
33class search_scheme_algorithm : protected policies_t...
34{
35private:
40
41 static_assert(!std::same_as<search_result_type, empty_type>, "The search result type was not configured.");
42
43public:
53
65 search_scheme_algorithm(configuration_t const & cfg, index_t const & index) : policies_t{cfg}...
66 {
67 stratum = cfg.get_or(search_cfg::hit_strata{0}).stratum;
68 index_ptr = std::addressof(index);
69 }
71
92 template <tuple_like indexed_query_t, typename callback_t>
93 requires (std::tuple_size_v<indexed_query_t> == 2)
94 && std::ranges::forward_range<std::tuple_element_t<1, indexed_query_t>>
95 && std::invocable<callback_t, search_result_type>
96 void operator()(indexed_query_t && indexed_query, callback_t && callback)
97 {
98 auto && [query_idx, query] = indexed_query;
99 auto error_state = this->max_error_counts(query); // see policy_max_error
100
101 // construct internal delegate for collecting hits for later filtering (if necessary)
103 auto on_hit_delegate = [&internal_hits](auto const & it)
104 {
105 internal_hits.push_back(it);
106 };
107
108 perform_search_by_hit_strategy(internal_hits, query, error_state, on_hit_delegate);
109
110 // Invoke the callback on the generated result.
111 this->make_results(std::move(internal_hits), query_idx, callback); // see policy_search_result_builder
112 }
113
114private:
116 index_t const * index_ptr{nullptr};
117
119 uint8_t stratum{};
120
121 // forward declaration
122 template <bool abort_on_hit, typename query_t, typename delegate_t>
123 inline void search_algo_bi(query_t & query, search_param const error_left, delegate_t && delegate);
124
132 template <typename query_t, typename delegate_t>
134 query_t & query,
135 search_param error_state,
136 delegate_t const & on_hit_delegate)
137 {
138 if constexpr (!traits_t::search_all_hits)
139 {
140 auto max_total = error_state.total;
141 error_state.total = 0; // start search with less errors
142 while (internal_hits.empty() && error_state.total <= max_total)
143 {
144 // * If you only want the best hit (traits_t::search_single_best_hit), you stop after finding the
145 // first hit, the hit with the least errors (`abort_on_hit` is true).
146 // * If you are in strata mode (traits_t::search_strata_hits), you do the same as with best hits,
147 // but then do the extra step afterwards (`abort_on_hit` is true).
148 // * If you want all best hits (traits_t::search_all_best_hits), you do not stop after the first
149 // hit but continue the current search algorithm/max_error pattern (`abort_on_hit` is true).
150 constexpr bool abort_on_hit = !traits_t::search_all_best_hits;
151 search_algo_bi<abort_on_hit>(query, error_state, on_hit_delegate);
152 ++error_state.total;
153 }
154 if constexpr (traits_t::search_strata_hits)
155 {
156 if (!internal_hits.empty())
157 {
158 internal_hits.clear(); // TODO:don't clear when using Optimum Search Schemes with lower error bounds
159 error_state.total += stratum - 1;
160 search_algo_bi<false>(query, error_state, on_hit_delegate);
161 }
162 }
163 }
164 else // detail::search_mode_all
165 {
166 // If you want to find all hits, you cannot stop once you found any hit (<false>)
167 // since you have to find all paths in the search tree that satisfy the hit condition.
168 search_algo_bi<false>(query, error_state, on_hit_delegate);
169 }
170 }
171};
172
186inline std::vector<search_dyn> compute_ss(uint8_t const min_error, uint8_t const max_error)
187{
188 // TODO: Replace this at least by the pigeonhole principle or even better by 01*0 schemes.
189 // NOTE: Make sure that the searches are sorted by their asymptotical running time (i.e. upper error bound string),
190 // s.t. easy to compute searches come first. This improves the running time of algorithms that abort after the
191 // first hit (e.g. search strategy: best). Even though it is not guaranteed, this seems to be a good greedy
192 // approach.
193 std::vector<search_dyn> scheme{{{1}, {min_error}, {max_error}}};
194 return scheme;
195}
196
214template <typename search_scheme_t>
215inline auto search_scheme_block_info(search_scheme_t const & search_scheme, size_t const query_length)
216{
217 using blocks_length_type = typename search_scheme_t::value_type::blocks_length_type;
218
219 constexpr bool is_dyn_scheme = std::same_as<search_scheme_t, search_scheme_dyn_type>;
220
221 // Either store information in an array (for search schemes known at compile time) or in a vector otherwise.
223 is_dyn_scheme,
227
228 result_type result;
229 if constexpr (is_dyn_scheme)
230 result.resize(search_scheme.size());
231
232 uint8_t const blocks{search_scheme[0].blocks()};
233 size_t const block_length{query_length / blocks};
234 uint8_t const rest{static_cast<uint8_t>(query_length % blocks)};
235
236 blocks_length_type blocks_length;
237 // set all blocks_length values to block_length
238 // resp. block_length + 1 for the first `rest = block_length % blocks` values
239 if constexpr (is_dyn_scheme)
240 blocks_length.resize(blocks, block_length);
241 else
242 blocks_length.fill(block_length);
243
244 for (uint8_t block_id = 0; block_id < rest; ++block_id)
245 ++blocks_length[block_id];
246
247 for (uint8_t search_id = 0; search_id < search_scheme.size(); ++search_id)
248 {
249 auto const & search = search_scheme[search_id];
250
251 auto & [search_blocks_length, start_pos] = result[search_id];
252
253 // compute cumulative blocks_length and starting position
254 start_pos = 0;
255 if constexpr (is_dyn_scheme)
256 search_blocks_length.resize(blocks);
257 search_blocks_length[0] = blocks_length[search.pi[0] - 1];
258 for (uint8_t i = 1; i < blocks; ++i)
259 {
260 search_blocks_length[i] = blocks_length[search.pi[i] - 1] + search_blocks_length[i - 1];
261 if (search.pi[i] < search.pi[0])
262 start_pos += search_blocks_length[i] - search_blocks_length[i - 1];
263 }
264 }
265
266 return result;
267}
268
270// forward declaration
271template <bool abort_on_hit,
272 typename cursor_t,
273 typename query_t,
274 typename search_t,
275 typename blocks_length_t,
276 typename delegate_t>
277inline bool search_ss(cursor_t cur,
278 query_t & query,
279 typename cursor_t::size_type const lb,
280 typename cursor_t::size_type const rb,
281 uint8_t const errors_spent,
282 uint8_t const block_id,
283 bool const go_right,
284 search_t const & search,
285 blocks_length_t const & blocks_length,
286 search_param const error_left,
287 delegate_t && delegate);
289
321template <bool abort_on_hit,
322 typename cursor_t,
323 typename query_t,
324 typename search_t,
325 typename blocks_length_t,
326 typename delegate_t>
327inline bool search_ss_exact(cursor_t cur,
328 query_t & query,
329 typename cursor_t::size_type const lb,
330 typename cursor_t::size_type const rb,
331 uint8_t const errors_spent,
332 uint8_t const block_id,
333 bool const go_right,
334 search_t const & search,
335 blocks_length_t const & blocks_length,
336 search_param const error_left,
337 delegate_t && delegate)
338{
339 using size_type = typename cursor_t::size_type;
340
341 uint8_t const block_id2 = std::min<uint8_t>(block_id + 1, search.blocks() - 1);
342 bool const go_right2 = (block_id < search.blocks() - 1) && (search.pi[block_id + 1] > search.pi[block_id]);
343
344 if (go_right)
345 {
346 size_type const infix_lb = rb - 1; // inclusive
347 size_type const infix_rb = lb + blocks_length[block_id] - 1; // exclusive
348
349 if (!cur.extend_right(query | views::slice(infix_lb, infix_rb + 1)))
350 return false;
351
352 if (search_ss<abort_on_hit>(cur,
353 query,
354 lb,
355 infix_rb + 2,
356 errors_spent,
357 block_id2,
358 go_right2,
359 search,
360 blocks_length,
361 error_left,
362 delegate)
363 && abort_on_hit)
364 {
365 return true;
366 }
367 }
368 else
369 {
370 size_type const infix_lb = rb - blocks_length[block_id] - 1; // inclusive
371 size_type const infix_rb = lb - 1; // inclusive
372
373 if (!cur.extend_left(query | views::slice(infix_lb, infix_rb + 1)))
374 return false;
375
376 if (search_ss<abort_on_hit>(cur,
377 query,
378 infix_lb,
379 rb,
380 errors_spent,
381 block_id2,
382 go_right2,
383 search,
384 blocks_length,
385 error_left,
386 delegate)
387 && abort_on_hit)
388 {
389 return true;
390 }
391 }
392 return false;
393}
394
401template <bool abort_on_hit,
402 typename cursor_t,
403 typename query_t,
404 typename search_t,
405 typename blocks_length_t,
406 typename delegate_t>
407inline bool search_ss_deletion(cursor_t cur,
408 query_t & query,
409 typename cursor_t::size_type const lb,
410 typename cursor_t::size_type const rb,
411 uint8_t const errors_spent,
412 uint8_t const block_id,
413 bool const go_right,
414 search_t const & search,
415 blocks_length_t const & blocks_length,
416 search_param const error_left,
417 delegate_t && delegate)
418{
419 uint8_t const max_error_left_in_block = search.u[block_id] - errors_spent;
420 uint8_t const min_error_left_in_block = std::max(search.l[block_id] - errors_spent, 0);
421
422 // Switch to the next block when the min number of errors is reached
423 if (min_error_left_in_block == 0)
424 {
425 uint8_t const block_id2 = std::min<uint8_t>(block_id + 1, search.blocks() - 1);
426 bool const go_right2 = block_id2 == 0 ? true : search.pi[block_id2] > search.pi[block_id2 - 1];
427
428 if (search_ss<abort_on_hit>(cur,
429 query,
430 lb,
431 rb,
432 errors_spent,
433 block_id2,
434 go_right2,
435 search,
436 blocks_length,
437 error_left,
438 delegate)
439 && abort_on_hit)
440 {
441 return true;
442 }
443 }
444
445 // Insert deletions into the current block as long as possible
446 // Do not allow deletions at the beginning of the leftmost block
447 // Do not allow deletions at the end of the rightmost block
448 if (!(search.pi[block_id] == 1 && !go_right) && !(search.pi[block_id] == search.blocks() && go_right)
449 && max_error_left_in_block > 0 && error_left.total > 0 && error_left.deletion > 0
450 && ((go_right && cur.extend_right()) || (!go_right && cur.extend_left())))
451 {
452 search_param error_left2{error_left};
453 error_left2.total--;
454 error_left2.deletion--;
455 do
456 {
457 if (search_ss_deletion<abort_on_hit>(cur,
458 query,
459 lb,
460 rb,
461 errors_spent + 1,
462 block_id,
463 go_right,
464 search,
465 blocks_length,
466 error_left2,
467 delegate)
468 && abort_on_hit)
469 {
470 return true;
471 }
472 }
473 while ((go_right && cur.cycle_back()) || (!go_right && cur.cycle_front()));
474 }
475 return false;
476}
477
486template <bool abort_on_hit,
487 typename cursor_t,
488 typename query_t,
489 typename search_t,
490 typename blocks_length_t,
491 typename delegate_t>
492inline bool search_ss_children(cursor_t cur,
493 query_t & query,
494 typename cursor_t::size_type const lb,
495 typename cursor_t::size_type const rb,
496 uint8_t const errors_spent,
497 uint8_t const block_id,
498 bool const go_right,
499 uint8_t const min_error_left_in_block,
500 search_t const & search,
501 blocks_length_t const & blocks_length,
502 search_param const error_left,
503 delegate_t && delegate)
504{
505 using size_type = typename cursor_t::size_type;
506 if ((go_right && cur.extend_right()) || (!go_right && cur.extend_left()))
507 {
508 size_type const chars_left = blocks_length[block_id] - (rb - lb - 1);
509
510 size_type lb2 = lb - !go_right;
511 size_type rb2 = rb + go_right;
512
513 do
514 {
515 bool const delta = cur.last_rank() != to_rank(query[(go_right ? rb : lb) - 1]);
516
517 // skip if there are more min errors left in the current block than characters in the block
518 // i.e. chars_left - 1 < min_error_left_in_block - delta
519 // TODO: move that outside the if / do-while struct
520 // TODO: incorporate error_left.deletion into formula
521 if (error_left.deletion == 0 && chars_left + delta < min_error_left_in_block + 1u)
522 continue;
523
524 if (!delta || error_left.substitution > 0)
525 {
526 search_param error_left2{error_left};
527 error_left2.total -= delta;
528 error_left2.substitution -= delta;
529
530 // At the end of the current block
531 if (rb - lb == blocks_length[block_id])
532 {
533 // Leave the possibility for one or multiple deletions at the end of a block.
534 // Thus do not change the direction (go_right) yet.
535 if (error_left.deletion > 0)
536 {
537 if (search_ss_deletion<abort_on_hit>(cur,
538 query,
539 lb2,
540 rb2,
541 errors_spent + delta,
542 block_id,
543 go_right,
544 search,
545 blocks_length,
546 error_left2,
547 delegate)
548 && abort_on_hit)
549 {
550 return true;
551 }
552 }
553 else
554 {
555 uint8_t const block_id2 = std::min<uint8_t>(block_id + 1, search.blocks() - 1);
556 bool const go_right2 = block_id2 == 0 ? true : search.pi[block_id2] > search.pi[block_id2 - 1];
557
558 if (search_ss<abort_on_hit>(cur,
559 query,
560 lb2,
561 rb2,
562 errors_spent + delta,
563 block_id2,
564 go_right2,
565 search,
566 blocks_length,
567 error_left2,
568 delegate)
569 && abort_on_hit)
570 {
571 return true;
572 }
573 }
574 }
575 else
576 {
577 if (search_ss<abort_on_hit>(cur,
578 query,
579 lb2,
580 rb2,
581 errors_spent + delta,
582 block_id,
583 go_right,
584 search,
585 blocks_length,
586 error_left2,
587 delegate)
588 && abort_on_hit)
589 {
590 return true;
591 }
592 }
593 }
594
595 // Deletion
596 // TODO: check whether the conditions for deletions at the beginning/end of the query are really necessary
597 // No deletion at the beginning of the leftmost block.
598 // No deletion at the end of the rightmost block.
599 if (error_left.deletion > 0 && !(go_right && (rb == 1 || rb == std::ranges::size(query) + 1))
600 && !(!go_right && (lb == 0 || lb == std::ranges::size(query))))
601 {
602 search_param error_left3{error_left};
603 error_left3.total--;
604 error_left3.deletion--;
605 search_ss<abort_on_hit>(cur,
606 query,
607 lb,
608 rb,
609 errors_spent + 1,
610 block_id,
611 go_right,
612 search,
613 blocks_length,
614 error_left3,
615 delegate);
616 }
617 }
618 while ((go_right && cur.cycle_back()) || (!go_right && cur.cycle_front()));
619 }
620 return false;
621}
622
628template <bool abort_on_hit,
629 typename cursor_t,
630 typename query_t,
631 typename search_t,
632 typename blocks_length_t,
633 typename delegate_t>
634inline bool search_ss(cursor_t cur,
635 query_t & query,
636 typename cursor_t::size_type const lb,
637 typename cursor_t::size_type const rb,
638 uint8_t const errors_spent,
639 uint8_t const block_id,
640 bool const go_right,
641 search_t const & search,
642 blocks_length_t const & blocks_length,
643 search_param const error_left,
644 delegate_t && delegate)
645{
646 uint8_t const max_error_left_in_block = search.u[block_id] - errors_spent;
647 uint8_t const min_error_left_in_block = std::max(search.l[block_id] - errors_spent, 0); // NOTE: changed
648
649 // Done.
650 if (min_error_left_in_block == 0 && lb == 0 && rb == std::ranges::size(query) + 1)
651 {
652 delegate(cur);
653 return true;
654 }
655 // Exact search in current block.
656 else if (((max_error_left_in_block == 0) && (rb - lb - 1 != blocks_length[block_id]))
657 || (error_left.total == 0 && min_error_left_in_block == 0))
658 {
659 if (search_ss_exact<abort_on_hit>(cur,
660 query,
661 lb,
662 rb,
663 errors_spent,
664 block_id,
665 go_right,
666 search,
667 blocks_length,
668 error_left,
669 delegate)
670 && abort_on_hit)
671 {
672 return true;
673 }
674 }
675 // Approximate search in current block.
676 // i.e. blocks_length[block_id] - (rb - lb - (lb != rb)) >= min_error_left_in_block
677 else if (error_left.total > 0)
678 {
679 // Insertion
680 if (error_left.insertion > 0)
681 {
682 using size_type = typename cursor_t::size_type;
683
684 size_type const lb2 = lb - !go_right;
685 size_type const rb2 = rb + go_right;
686
687 search_param error_left2{error_left};
688 error_left2.total--;
689 error_left2.insertion--;
690 // At the end of the current block
691 if (rb - lb == blocks_length[block_id])
692 {
693 // Leave the possibility for one or multiple deletions at the end of a block.
694 // Thus do not change the direction (go_right) yet.
695 // TODO: benchmark the improvement on preventing insertions followed by a deletion and vice versa. Does
696 // it pay off the additional complexity and documentation for the user? (Note that the user might only
697 // allow for insertions and deletion and not for mismatches).
698 if (search_ss_deletion<abort_on_hit>(cur,
699 query,
700 lb2,
701 rb2,
702 errors_spent + 1,
703 block_id,
704 go_right,
705 search,
706 blocks_length,
707 error_left2,
708 delegate)
709 && abort_on_hit)
710 {
711 return true;
712 }
713 }
714 else
715 {
716 if (search_ss<abort_on_hit>(cur,
717 query,
718 lb2,
719 rb2,
720 errors_spent + 1,
721 block_id,
722 go_right,
723 search,
724 blocks_length,
725 error_left2,
726 delegate)
727 && abort_on_hit)
728 {
729 return true;
730 }
731 }
732 }
733 if (search_ss_children<abort_on_hit>(cur,
734 query,
735 lb,
736 rb,
737 errors_spent,
738 block_id,
739 go_right,
740 min_error_left_in_block,
741 search,
742 blocks_length,
743 error_left,
744 delegate)
745 && abort_on_hit)
746 {
747 return true;
748 }
749 }
750 return false;
751}
752
776template <bool abort_on_hit, typename index_t, typename query_t, typename search_scheme_t, typename delegate_t>
777inline void search_ss(index_t const & index,
778 query_t & query,
779 search_param const error_left,
780 search_scheme_t const & search_scheme,
781 delegate_t && delegate)
782{
783 // retrieve cumulative block lengths and starting position
784 auto const block_info = search_scheme_block_info(search_scheme, std::ranges::size(query));
785
786 for (uint8_t search_id = 0; search_id < search_scheme.size(); ++search_id)
787 {
788 auto const & search = search_scheme[search_id];
789 auto const & [blocks_length, start_pos] = block_info[search_id];
790
791 bool const hit = search_ss<abort_on_hit>(index.cursor(), // cursor on the index
792 query, // query to be searched
793 start_pos,
794 start_pos + 1, // infix range already searched (open interval)
795 // the first character of `query` has the index 1 (not 0)
796 0, // errors spent
797 0, // current block id in search scheme
798 true, // search the first block from left to right
799 search,
800 blocks_length, // search scheme information
801 error_left, // errors left (broken down by error types)
802 delegate // delegate function called on hit
803 );
804
805 if (abort_on_hit && hit)
806 return;
807 }
808}
809
828template <typename configuration_t, typename index_t, typename... policies_t>
830template <bool abort_on_hit, typename query_t, typename delegate_t>
832 query_t & query,
833 search_param const error_left,
834 delegate_t && delegate)
835{
836 switch (error_left.total)
837 {
838 case 0:
839 search_ss<abort_on_hit>(*index_ptr, query, error_left, optimum_search_scheme<0, 0>, delegate);
840 break;
841 case 1:
842 search_ss<abort_on_hit>(*index_ptr, query, error_left, optimum_search_scheme<0, 1>, delegate);
843 break;
844 case 2:
845 search_ss<abort_on_hit>(*index_ptr, query, error_left, optimum_search_scheme<0, 2>, delegate);
846 break;
847 case 3:
848 search_ss<abort_on_hit>(*index_ptr, query, error_left, optimum_search_scheme<0, 3>, delegate);
849 break;
850 default:
851 auto const & search_scheme{compute_ss(0, error_left.total)};
852 search_ss<abort_on_hit>(*index_ptr, query, error_left, search_scheme, delegate);
853 break;
854 }
855}
856
857} // namespace seqan3::detail
T addressof(T... args)
Provides the bidirectional seqan3::bi_fm_index.
The algorithm that performs a bidirectional search on a bidirectional FM index using (optimal) search...
Definition search_scheme_algorithm.hpp:34
void perform_search_by_hit_strategy(std::vector< typename index_t::cursor_type > &internal_hits, query_t &query, search_param error_state, delegate_t const &on_hit_delegate)
Calls search_algo_bi depending on the search strategy (hit configuration) given in the configuration.
Definition search_scheme_algorithm.hpp:133
~search_scheme_algorithm()=default
Defaulted.
search_scheme_algorithm(search_scheme_algorithm const &)=default
Defaulted.
typename traits_t::search_result_type search_result_type
The search result type.
Definition search_scheme_algorithm.hpp:39
search_scheme_algorithm & operator=(search_scheme_algorithm &&)=default
Defaulted.
search_scheme_algorithm(search_scheme_algorithm &&)=default
Defaulted.
search_scheme_algorithm(configuration_t const &cfg, index_t const &index)
Constructs from a configuration object and an index.
Definition search_scheme_algorithm.hpp:65
search_scheme_algorithm & operator=(search_scheme_algorithm const &)=default
Defaulted.
search_scheme_algorithm()=default
Defaulted.
Configuration element to receive all hits with the best number of errors plus the given stratum....
Definition hit.hpp:107
T clear(T... args)
T empty(T... args)
@ result_type
ID for the result_type option.
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition alphabet/concept.hpp:152
@ hit
Identifier for the hit configuration (all, all_best, single_best, strata).
auto search_scheme_block_info(search_scheme_t const &search_scheme, size_t const query_length)
Returns for each search the cumulative length of blocks in the order of blocks in each search and the...
Definition search_scheme_algorithm.hpp:215
bool search_ss(cursor_t cur, query_t &query, typename cursor_t::size_type const lb, typename cursor_t::size_type const rb, uint8_t const errors_spent, uint8_t const block_id, bool const go_right, search_t const &search, blocks_length_t const &blocks_length, search_param const error_left, delegate_t &&delegate)
Searches a query sequence in a bidirectional index using a single search of a search schemes.
Definition search_scheme_algorithm.hpp:634
bool search_ss_children(cursor_t cur, query_t &query, typename cursor_t::size_type const lb, typename cursor_t::size_type const rb, uint8_t const errors_spent, uint8_t const block_id, bool const go_right, uint8_t const min_error_left_in_block, search_t const &search, blocks_length_t const &blocks_length, search_param const error_left, delegate_t &&delegate)
Searches a query sequence in a bidirectional index using a single search of a search schemes....
Definition search_scheme_algorithm.hpp:492
bool search_ss_exact(cursor_t cur, query_t &query, typename cursor_t::size_type const lb, typename cursor_t::size_type const rb, uint8_t const errors_spent, uint8_t const block_id, bool const go_right, search_t const &search, blocks_length_t const &blocks_length, search_param const error_left, delegate_t &&delegate)
Searches a query sequence in a bidirectional index using a single search of a search scheme....
Definition search_scheme_algorithm.hpp:327
bool search_ss_deletion(cursor_t cur, query_t &query, typename cursor_t::size_type const lb, typename cursor_t::size_type const rb, uint8_t const errors_spent, uint8_t const block_id, bool const go_right, search_t const &search, blocks_length_t const &blocks_length, search_param const error_left, delegate_t &&delegate)
Searches a query sequence in a bidirectional index using a single search of a search schemes....
Definition search_scheme_algorithm.hpp:407
std::vector< search_dyn > compute_ss(uint8_t const min_error, uint8_t const max_error)
Computes a (non-optimal) search scheme. Currently the generated search scheme represents trivial back...
Definition search_scheme_algorithm.hpp:186
typename transformation_trait_or< type_t, default_t >::type transformation_trait_or_t
Helper type of seqan3::detail::transformation_trait_or (transformation_trait shortcut).
Definition transformation_trait_or.hpp:48
constexpr auto slice
A view adaptor that returns a half-open interval on the underlying range.
Definition slice.hpp:175
Provides concept seqan3::template_specialisation_of<mytype, [...]> for checking the type specialisati...
T max(T... args)
The internal SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
T push_back(T... args)
Provides the concept for seqan3::detail::sdsl_index.
Provides data structures used by different search algorithms.
Provides the data structures and precomputed instances for (optimum) search schemes.
Provides seqan3::detail::search_traits.
Provides seqan3::views::slice.
Object grouping numbers of errors for different kind of error types.
Definition search_common.hpp:22
uint8_t insertion
Total number of insertion errors.
Definition search_common.hpp:28
uint8_t total
Total number of errors (upper bound over all error types).
Definition search_common.hpp:24
uint8_t deletion
Total number of deletion errors.
Definition search_common.hpp:30
uint8_t substitution
Total number of substitution errors.
Definition search_common.hpp:26
A collection of traits extracted from the search configuration.
Definition search_traits.hpp:31
typename std::remove_cvref_t< decltype(std::declval< search_configuration_t >().get_or(search_cfg::detail::result_type< empty_search_result_type >{}))>::type search_result_type
The configured search result type.
Definition search_traits.hpp:36
Object storing information for a search (of a search scheme).
Definition search_scheme_precomputed.hpp:25
constexpr uint8_t blocks() const noexcept
Returns the number of blocks.
Definition search_scheme_precomputed.hpp:37
std::array< uint8_t, nbr_blocks > u
Upper error bound for each block (accumulated values)
Definition search_scheme_precomputed.hpp:34
std::array< uint8_t, nbr_blocks > l
Lower error bound for each block (accumulated values)
Definition search_scheme_precomputed.hpp:32
std::array< uint8_t, nbr_blocks > pi
Order of blocks.
Definition search_scheme_precomputed.hpp:30
Provides seqan3::detail::transformation_trait_or.
Hide me