SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
alignment_configurator.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 <functional>
13#include <tuple>
14#include <utility>
15#include <vector>
16
61
62namespace seqan3::detail
63{
64
74template <typename range_type, typename alignment_config_type>
76{
77private:
84 using first_seq_t = std::tuple_element_t<0, std::ranges::range_value_t<unref_range_type>>;
86 using second_seq_t = std::tuple_element_t<1, std::ranges::range_value_t<unref_range_type>>;
88
89public:
91 static constexpr bool expects_tuple_like_value_type()
92 {
94 && std::tuple_size_v<std::ranges::range_value_t<unref_range_type>> == 2;
95 }
96
98 static constexpr bool expects_valid_scoring_scheme()
99 {
100 if constexpr (alignment_config_type::template exists<align_cfg::scoring_scheme>())
101 {
102 using scoring_type = std::remove_reference_t<
103 decltype(get<align_cfg::scoring_scheme>(std::declval<alignment_config_type>()).scheme)>;
104 return static_cast<bool>(scoring_scheme_for<scoring_type,
105 std::ranges::range_value_t<first_seq_t>,
106 std::ranges::range_value_t<second_seq_t>>);
107 }
108 else
109 {
110 return false;
111 }
112 }
113
115 static constexpr bool expects_alignment_configuration()
116 {
117 bool const is_global = alignment_config_type::template exists<seqan3::align_cfg::method_global>();
118 bool const is_local = alignment_config_type::template exists<seqan3::align_cfg::method_local>();
119
120 return (is_global || is_local);
121 }
122};
123
129{
130private:
134 template <typename traits_t>
157
161 template <typename traits_t>
176
183 template <typename traits_t>
185 {
186 private:
188 using score_t = typename traits_t::score_type;
189
190 public:
192 using type = std::conditional_t<traits_t::is_vectorised,
195 };
196
198 template <typename traits_t, typename... args_t>
199 using select_alignment_algorithm_t = lazy_conditional_t<traits_t::is_banded,
202
206 template <typename config_t>
230
231public:
258 template <align_pairwise_range_input sequences_t, typename config_t>
259 requires is_type_specialisation_of_v<config_t, configuration>
260 static constexpr auto configure(config_t const & cfg)
261 {
262 auto config_with_output = maybe_default_output(cfg);
263 using config_with_output_t = decltype(config_with_output);
264
265 // ----------------------------------------------------------------------------
266 // Configure the type-erased alignment function.
267 // ----------------------------------------------------------------------------
268
269 using first_seq_t = std::tuple_element_t<0, std::ranges::range_value_t<sequences_t>>;
270 using second_seq_t = std::tuple_element_t<1, std::ranges::range_value_t<sequences_t>>;
271
272 using wrapped_first_t = type_reduce_t<first_seq_t &>;
273 using wrapped_second_t = type_reduce_t<second_seq_t &>;
274
275 // The alignment executor passes a chunk over an indexed sequence pair range to the alignment algorithm.
276 using indexed_sequence_pair_range_t = typename chunked_indexed_sequence_pairs<sequences_t>::type;
277 using indexed_sequence_pair_chunk_t = std::ranges::range_value_t<indexed_sequence_pair_range_t>;
278
279 // Select the result type based on the sequences and the configuration.
280 using alignment_result_value_t = typename align_result_selector<std::remove_reference_t<wrapped_first_t>,
282 config_with_output_t>::type;
283 using alignment_result_t = alignment_result<alignment_result_value_t>;
284 using callback_on_result_t = std::function<void(alignment_result_t)>;
285 // Define the function wrapper type.
286 using function_wrapper_t = std::function<void(indexed_sequence_pair_chunk_t, callback_on_result_t)>;
287
288 // Capture the alignment result type.
289 auto config_with_result_type = config_with_output | align_cfg::detail::result_type<alignment_result_t>{};
290
291 // ----------------------------------------------------------------------------
292 // Test some basic preconditions
293 // ----------------------------------------------------------------------------
294
296
297 static_assert(alignment_contract_t::expects_alignment_configuration(),
298 "Alignment configuration error: "
299 "The alignment can only be configured with alignment configurations.");
300
301 static_assert(alignment_contract_t::expects_tuple_like_value_type(),
302 "Alignment configuration error: "
303 "The value type of the sequence ranges must model the seqan3::tuple_like and must contain "
304 "exactly 2 elements.");
305
306 static_assert(alignment_contract_t::expects_valid_scoring_scheme(),
307 "Alignment configuration error: "
308 "Either the scoring scheme was not configured or the given scoring scheme cannot be invoked with "
309 "the value types of the passed sequences.");
310
311 // ----------------------------------------------------------------------------
312 // Configure the algorithm
313 // ----------------------------------------------------------------------------
314
315 // Use default edit distance if gaps are not set.
316 align_cfg::gap_cost_affine edit_gap_cost{};
317 auto const & gap_cost = config_with_result_type.get_or(edit_gap_cost);
318 auto const & scoring_scheme = get<align_cfg::scoring_scheme>(cfg).scheme;
319
320 if constexpr (config_t::template exists<seqan3::align_cfg::method_global>())
321 {
322 // Only use edit distance if ...
323 if constexpr (std::same_as<std::remove_cvref_t<decltype(scoring_scheme)>, hamming_scoring_scheme>)
324 {
325 auto method_global_cfg = get<seqan3::align_cfg::method_global>(config_with_result_type);
326 // and ...
327 if (gap_cost.open_score == 0 && gap_cost.extension_score == -1
328 && // gap open score is not set and extension is -1,
329 !(method_global_cfg.free_end_gaps_sequence2_leading
330 || method_global_cfg.free_end_gaps_sequence2_trailing)
331 && // none of the free end gaps are set for second seq,
332 (method_global_cfg.free_end_gaps_sequence1_leading
333 == method_global_cfg
334 .free_end_gaps_sequence1_trailing)) // free ends for leading and trailing gaps are equal in first seq.
335 {
336
337 return std::pair{configure_edit_distance<function_wrapper_t>(config_with_result_type),
338 config_with_result_type};
339 }
340 }
341 }
342
343 // ----------------------------------------------------------------------------
344 // Check if invalid configuration was used.
345 // ----------------------------------------------------------------------------
346
347 // Do not allow min score configuration for alignments not computing the edit distance.
348 if (config_t::template exists<align_cfg::min_score>())
349 throw invalid_alignment_configuration{"The align_cfg::min_score configuration is only allowed for the "
350 "specific edit distance computation."};
351 // Configure the alignment algorithm.
352 return std::pair{configure_scoring_scheme<function_wrapper_t>(config_with_result_type),
353 config_with_result_type};
354 }
355
356private:
366 template <typename config_t>
367 static constexpr auto maybe_default_output(config_t const & config) noexcept
368 {
370
371 if constexpr (traits_t::has_output_configuration)
372 return config;
373 else
377 }
378
384 template <typename function_wrapper_t, typename config_t>
385 static constexpr function_wrapper_t configure_edit_distance(config_t const & cfg)
386 {
388
389 // ----------------------------------------------------------------------------
390 // Unsupported configurations
391 // ----------------------------------------------------------------------------
392
393 if constexpr (traits_t::is_banded)
394 throw invalid_alignment_configuration{"Banded alignments are yet not supported."};
395
396 // ----------------------------------------------------------------------------
397 // Configure semi-global alignment
398 // ----------------------------------------------------------------------------
399
400 // Get the value for the sequence ends configuration.
401 auto method_global_cfg = cfg.get_or(align_cfg::method_global{});
402
403 auto configure_edit_traits = [&](auto is_semi_global)
404 {
405 struct edit_traits_type
406 {
407 using is_semi_global_type [[maybe_unused]] = std::remove_cvref_t<decltype(is_semi_global)>;
408 };
409
410 edit_distance_algorithm<std::remove_cvref_t<config_t>, edit_traits_type> algorithm{cfg};
411 return function_wrapper_t{std::move(algorithm)};
412 };
413
414 // Check if it has free ends set for the first sequence trailing gaps.
415 auto has_free_ends_trailing = [&](auto first) constexpr
416 {
417 if constexpr (!decltype(first)::value)
418 {
419 return configure_edit_traits(std::false_type{});
420 }
421 else // Resolve correct property at runtime.
422 {
423 if (method_global_cfg.free_end_gaps_sequence1_trailing)
424 return configure_edit_traits(std::true_type{});
425 else
426 return configure_edit_traits(std::false_type{});
427 }
428 };
429
430 // Check if it has free ends set for the first sequence leading gaps.
431 if (method_global_cfg.free_end_gaps_sequence1_leading)
432 return has_free_ends_trailing(std::true_type{});
433 else
434 return has_free_ends_trailing(std::false_type{});
435 }
436
453 template <typename function_wrapper_t, typename config_t>
454 static constexpr function_wrapper_t configure_scoring_scheme(config_t const & cfg);
455
470 template <typename function_wrapper_t, typename... policies_t, typename config_t>
471 static constexpr function_wrapper_t make_algorithm(config_t const & cfg)
472 {
474
475 // Temporarily we will use the new and the old alignment implementation in order to
476 // refactor step-by-step to the new implementation. The new implementation will be tested in
477 // macrobenchmarks to show that it maintains a high performance.
478
479 // Use old alignment implementation if...
480 if constexpr (traits_t::is_local || // it is a local alignment,
481 traits_t::is_debug || // it runs in debug mode,
482 traits_t::compute_sequence_alignment || // it computes more than the begin position.
483 (traits_t::is_banded && traits_t::compute_begin_positions)
484 || // banded && more than end positions.
485 (traits_t::is_vectorised && traits_t::compute_end_positions)) // simd and more than the score.
486 {
487 using matrix_policy_t = typename select_matrix_policy<traits_t>::type;
488 using gap_policy_t = typename select_gap_policy<traits_t>::type;
489 using find_optimum_t = typename select_find_optimum_policy<traits_t>::type;
490 using gap_init_policy_t = deferred_crtp_base<affine_gap_init_policy>;
491
492 return alignment_algorithm<config_t,
493 matrix_policy_t,
494 gap_policy_t,
495 find_optimum_t,
496 gap_init_policy_t,
497 policies_t...>{cfg};
498 }
499 else // Use new alignment algorithm implementation.
500 {
501 //----------------------------------------------------------------------------------------------------------
502 // Configure the optimum tracker policy.
503 //----------------------------------------------------------------------------------------------------------
504
505 using scalar_optimum_updater_t =
507
508 using optimum_tracker_policy_t =
509 lazy_conditional_t<traits_t::is_vectorised,
512
513 //----------------------------------------------------------------------------------------------------------
514 // Configure the gap scheme policy.
515 //----------------------------------------------------------------------------------------------------------
516
517 using gap_cost_policy_t = typename select_gap_recursion_policy<config_t>::type;
518
519 //----------------------------------------------------------------------------------------------------------
520 // Configure the result builder policy.
521 //----------------------------------------------------------------------------------------------------------
522
523 using result_builder_policy_t = policy_alignment_result_builder<config_t>;
524
525 //----------------------------------------------------------------------------------------------------------
526 // Configure the scoring scheme policy.
527 //----------------------------------------------------------------------------------------------------------
528
529 using alignment_method_t = std::
530 conditional_t<traits_t::is_global, seqan3::align_cfg::method_global, seqan3::align_cfg::method_local>;
531
532 using score_t = typename traits_t::score_type;
533 using scoring_scheme_t = typename traits_t::scoring_scheme_type;
534 constexpr bool is_aminoacid_scheme =
535 is_type_specialisation_of_v<scoring_scheme_t, aminoacid_scoring_scheme>;
536
537 using simple_simd_scheme_t = lazy_conditional_t<traits_t::is_vectorised,
539 score_t,
540 typename traits_t::scoring_scheme_alphabet_type,
541 alignment_method_t>,
542 void>;
543 using matrix_simd_scheme_t = lazy_conditional_t<traits_t::is_vectorised,
545 score_t,
546 typename traits_t::scoring_scheme_alphabet_type,
547 alignment_method_t>,
548 void>;
549
550 using alignment_scoring_scheme_t =
551 std::conditional_t<traits_t::is_vectorised,
553 scoring_scheme_t>;
554
556
557 //----------------------------------------------------------------------------------------------------------
558 // Configure the alignment matrix policy.
559 //----------------------------------------------------------------------------------------------------------
560
561 using score_matrix_t = score_matrix_single_column<score_t>;
562 using trace_matrix_t = trace_matrix_full<trace_directions>;
563
564 using alignment_matrix_t =
565 std::conditional_t<traits_t::requires_trace_information,
567 score_matrix_t>;
568 using alignment_matrix_policy_t = policy_alignment_matrix<traits_t, alignment_matrix_t>;
569
570 //----------------------------------------------------------------------------------------------------------
571 // Configure the final alignment algorithm.
572 //----------------------------------------------------------------------------------------------------------
573
574 using algorithm_t = select_alignment_algorithm_t<traits_t,
575 config_t,
576 gap_cost_policy_t,
577 optimum_tracker_policy_t,
578 result_builder_policy_t,
579 scoring_scheme_policy_t,
580 alignment_matrix_policy_t>;
581 return algorithm_t{cfg};
582 }
583 }
584};
585
587template <typename function_wrapper_t, typename config_t>
588constexpr function_wrapper_t alignment_configurator::configure_scoring_scheme(config_t const & cfg)
589{
590 using traits_t = alignment_configuration_traits<config_t>;
591
592 using scoring_scheme_t = typename traits_t::scoring_scheme_type;
593 constexpr bool is_aminoacid_scheme = is_type_specialisation_of_v<scoring_scheme_t, aminoacid_scoring_scheme>;
594 using alignment_type_t = typename std::
595 conditional_t<traits_t::is_global, seqan3::align_cfg::method_global, seqan3::align_cfg::method_local>;
596
597 using simple_simd_scheme_t = lazy_conditional_t<traits_t::is_vectorised,
598 lazy<simd_match_mismatch_scoring_scheme,
599 typename traits_t::score_type,
600 typename traits_t::scoring_scheme_alphabet_type,
601 alignment_type_t>,
602 void>;
603 using matrix_simd_scheme_t = lazy_conditional_t<traits_t::is_vectorised,
604 lazy<simd_matrix_scoring_scheme,
605 typename traits_t::score_type,
606 typename traits_t::scoring_scheme_alphabet_type,
607 alignment_type_t>,
608 void>;
609
610 using alignment_scoring_scheme_t =
611 std::conditional_t<traits_t::is_vectorised,
613 scoring_scheme_t>;
614
615 using scoring_scheme_policy_t = deferred_crtp_base<scoring_scheme_policy, alignment_scoring_scheme_t>;
616 return make_algorithm<function_wrapper_t, scoring_scheme_policy_t>(cfg);
617}
619} // namespace seqan3::detail
Provides seqan3::detail::affine_gap_init_policy.
Provides seqan3::detail::affine_gap_policy.
Provides configuration for alignment output.
Provides seqan3::align_cfg::detail::result_type.
Provides seqan3::detail::align_result_selector.
Provides concepts needed internally for the alignment algorithms.
Provides helper type traits for the configuration and execution of the alignment algorithm.
Provides seqan3::detail::alignment_algorithm.
Provides seqan3::detail::alignment_matrix_policy.
Provides seqan3::alignment_result.
Provides seqan3::detail::alignment_score_matrix_one_column.
Provides seqan3::detail::alignment_score_matrix_one_column_banded.
Provides seqan3::detail::alignment_trace_matrix_full.
Provides seqan3::detail::alignment_trace_matrix_full_banded.
Provides seqan3::aminoacid_scoring_scheme.
Configuration element capturing the configured seqan3::alignment_result for the alignment algorithm.
Definition align_config_result_type.hpp:42
A configuration element for the affine gap cost scheme.
Definition align_config_gap_cost_affine.hpp:72
Sets the global alignment method.
Definition align_config_method.hpp:119
Configures the alignment result to output the alignment.
Definition align_config_output.hpp:168
Configures the alignment result to output the begin positions.
Definition align_config_output.hpp:128
Configures the alignment result to output the end position.
Definition align_config_output.hpp:84
Configures the alignment result to output the score.
Definition align_config_output.hpp:40
Configures the alignment result to output the id of the first sequence.
Definition align_config_output.hpp:208
Configures the alignment result to output the id of the second sequence.
Definition align_config_output.hpp:247
Stores the alignment results and gives access to score, alignment and the front and end positions.
Definition alignment_result.hpp:145
The alignment algorithm type to compute standard pairwise alignment using dynamic programming.
Definition alignment_algorithm.hpp:75
A banded alignment score matrix storing only a single banded column for the computation.
Definition alignment_score_matrix_one_column_banded.hpp:42
An alignment score matrix storing only a single column for the computation.
Definition alignment_score_matrix_one_column.hpp:42
An alignment traceback matrix storing the entire banded traceback matrix.
Definition alignment_trace_matrix_full_banded.hpp:53
An alignment traceback matrix storing the entire traceback matrix.
Definition alignment_trace_matrix_full.hpp:50
An alignment matrix that combines a score matrix with a trace matrix into a common interface.
Definition combined_score_and_trace_matrix.hpp:45
This algorithm unifies different edit distance implementations and uses the appropriate one depending...
Definition edit_distance_algorithm.hpp:37
The alignment algorithm type to compute the banded standard pairwise alignment using dynamic programm...
Definition pairwise_alignment_algorithm_banded.hpp:30
The alignment algorithm type to compute standard pairwise alignment using dynamic programming.
Definition pairwise_alignment_algorithm.hpp:44
Implements the alignment recursion function for the banded alignment algorithm using affine gap costs...
Definition policy_affine_gap_recursion_banded.hpp:23
Implements the alignment recursion function for the alignment algorithm using affine gap costs.
Definition policy_affine_gap_recursion.hpp:42
Implements the alignment recursion function for the banded alignment algorithm using affine gap costs...
Definition policy_affine_gap_with_trace_recursion_banded.hpp:25
Implements the alignment recursion function for the alignment algorithm using affine gap costs with t...
Definition policy_affine_gap_with_trace_recursion.hpp:24
A policy that provides a common interface to acquire the correct alignment matrices.
Definition policy_alignment_matrix.hpp:44
Implements the alignment result builder.
Definition policy_alignment_result_builder.hpp:34
Stores the configured scoring scheme used for this algorithm.
Definition policy_scoring_scheme.hpp:32
Score matrix for the pairwise alignment using only a single column.
Definition score_matrix_single_column.hpp:51
A vectorised scoring scheme handling matches and mismatches only.
Definition simd_match_mismatch_scoring_scheme.hpp:66
A vectorised scoring scheme to handle scoring matrices using gather strategy.
Definition simd_matrix_scoring_scheme.hpp:56
Trace matrix for the pairwise alignment using the full trace matrix.
Definition trace_matrix_full.hpp:50
A scoring scheme that assigns a score of 0 to matching letters and -1 to mismatching letters.
Definition hamming_scoring_scheme.hpp:33
Thrown if the configuration of the alignment algorithm is invalid.
Definition alignment/exception.hpp:32
Provides seqan3::detail::combined_score_and_trace_matrix.
Provides seqan3::detail::deferred_crtp_base.
Provides seqan3::detail::edit_distance_algorithm.
Provides seqan3::detail::find_optimum_policy.
A concept that requires that type be able to score two letters.
Whether a type behaves like a tuple.
Provides lazy template instantiation traits.
The internal SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
decltype(views::type_reduce(std::declval< t >())) type_reduce_t
Deduces the return value of seqan3::views::type_reduce.
Definition type_reduce.hpp:159
Provides seqan3::nucleotide_scoring_scheme.
Provides seqan3::detail::pairwise_alignment_algorithm.
Provides seqan3::detail::pairwise_alignment_algorithm.
Provides seqan3::detail::policy_affine_gap_recursion.
Provides seqan3::detail::policy_affine_gap_recursion_banded.
Provides seqan3::detail::policy_affine_gap_with_trace_recursion.
Provides seqan3::detail::policy_affine_gap_with_trace_recursion_banded.
Provides seqan3::detail::policy_alignment_matrix.
Provides seqan3::detail::policy_alignment_result_builder.
Provides seqan3::detail::policy_optimum_tracker.
Provides seqan3::detail::policy_optimum_tracker_simd.
Provides seqan3::detail::policy_scoring_scheme.
Provides seqan3::detail::score_matrix_single_column.
Provides seqan3::detail::scoring_scheme_policy.
Provides seqan3::simd::simd_type.
Provides seqan3::detail::simd_affine_gap_policy.
Provides seqan3::detail::simd_find_optimum_policy.
Provides seqan3::detail::simd_match_mismatch_scoring_scheme.
Provides seqan3::detail::simd_matrix_scoring_scheme.
Helper metafunction to select the alignment result type based on the configuration.
Definition align_result_selector.hpp:42
A traits type for the alignment algorithm that exposes static information stored within the alignment...
Definition alignment/pairwise/detail/type_traits.hpp:80
static constexpr bool requires_trace_information
Flag indicating whether the trace matrix needs to be computed.
Definition alignment/pairwise/detail/type_traits.hpp:171
Transformation trait that chooses the correct find optimum policy.
Definition alignment_configurator.hpp:185
typename traits_t::score_type score_t
The score type for the alignment computation.
Definition alignment_configurator.hpp:188
Transformation trait that chooses the correct gap policy.
Definition alignment_configurator.hpp:163
typename traits_t::score_type score_t
The score type for the alignment computation.
Definition alignment_configurator.hpp:166
Selects the gap recursion policy.
Definition alignment_configurator.hpp:208
static constexpr bool with_trace
A flag indicating if trace is required.
Definition alignment_configurator.hpp:213
Transformation trait that chooses the correct matrix policy.
Definition alignment_configurator.hpp:136
static constexpr bool only_coordinates
Indicates whether only the coordinate is required to compute the alignment.
Definition alignment_configurator.hpp:139
Configures the alignment algorithm given the sequences and the configuration object.
Definition alignment_configurator.hpp:129
static constexpr auto maybe_default_output(config_t const &config) noexcept
Adds maybe the default output arguments if the user did not provide any.
Definition alignment_configurator.hpp:367
lazy_conditional_t< traits_t::is_banded, lazy< pairwise_alignment_algorithm_banded, args_t... >, lazy< pairwise_alignment_algorithm, args_t... > > select_alignment_algorithm_t
Selects either the banded or the unbanded alignment algorithm based on the given traits type.
Definition alignment_configurator.hpp:201
static constexpr function_wrapper_t make_algorithm(config_t const &cfg)
Constructs the actual alignment algorithm wrapped in the passed std::function object.
Definition alignment_configurator.hpp:471
static constexpr function_wrapper_t configure_edit_distance(config_t const &cfg)
Configures the edit distance algorithm.
Definition alignment_configurator.hpp:385
static constexpr auto configure(config_t const &cfg)
Configures the algorithm.
Definition alignment_configurator.hpp:260
static constexpr function_wrapper_t configure_scoring_scheme(config_t const &cfg)
Configures the scoring scheme to use for the alignment computation.
Provides several contracts to test when configuring the alignment algorithm.
Definition alignment_configurator.hpp:76
static constexpr bool expects_tuple_like_value_type()
Tests whether the value type of range_type is a tuple with exactly 2 members.
Definition alignment_configurator.hpp:91
static constexpr bool expects_valid_scoring_scheme()
Tests whether the scoring scheme is set and can be invoked with the sequences passed.
Definition alignment_configurator.hpp:98
std::tuple_element_t< 0, std::ranges::range_value_t< unref_range_type > > first_seq_t
The type of the first sequence.
Definition alignment_configurator.hpp:84
std::tuple_element_t< 1, std::ranges::range_value_t< unref_range_type > > second_seq_t
The type of the second sequence.
Definition alignment_configurator.hpp:86
static constexpr bool expects_alignment_configuration()
Expects alignment configurations.
Definition alignment_configurator.hpp:115
decltype(views::zip(std::declval< sequence_pairs_t >(), std::views::iota(0))|views::chunk(1)) type
The transformed type that models seqan3::detail::indexed_sequence_pair_range.
Definition alignment/pairwise/detail/type_traits.hpp:63
An invocable wrapper that defers the instantiation of a crtp_base class.
Definition deferred_crtp_base.hpp:40
An empty type whose only purpose is to hold an uninstantiated template plus its arguments.
Definition lazy_conditional.hpp:30
Provides type traits for working with templates.
Provides seqan3::detail::trace_matrix_full.
Provides seqan3::views::type_reduce.
Provides seqan3::tuple_like.
Provides seqan3::views::zip.
Hide me