SeqAn3  3.1.0-rc.1
The Modern C++ library for sequence analysis.
search_configurator.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2021, 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 
27 
28 namespace seqan3::detail
29 {
30 
34 class search_configurator
35 {
36 private:
43  template <typename search_configuration_t, typename index_t, typename query_index_t>
44  struct select_search_result
45  {
46  private:
48  using index_cursor_type = typename index_t::cursor_type;
50  using index_size_type = typename index_t::size_type;
52  using traits_type = search_traits<search_configuration_t>;
53 
61  using reference_begin_position_t = std::conditional_t<traits_type::output_reference_begin_position,
62  index_size_type,
63  empty_type>;
64 
65  public:
67  using type = search_result<query_id_t, index_cursor_t, reference_id_t, reference_begin_position_t>;
68  };
69 
76  template <typename configuration_t, typename index_t, typename ...policies_t>
77  struct select_search_algorithm
78  {
80  using type =
81  lazy_conditional_t<template_specialisation_of<typename index_t::cursor_type, bi_fm_index_cursor>,
82  lazy<search_scheme_algorithm, configuration_t, index_t, policies_t...>,
83  lazy<unidirectional_search_algorithm, configuration_t, index_t, policies_t...>>;
84  };
85 
86 public:
97  template <typename configuration_t>
98  static auto add_default_hit_configuration(configuration_t const & cfg)
99  {
100  if constexpr (!detail::search_traits<configuration_t>::has_hit_configuration)
101  return cfg | search_cfg::hit_all{};
102  else
103  return cfg;
104  }
105 
115  template <typename configuration_t>
116  static auto add_default_output_configuration(configuration_t const & cfg)
117  {
118  if constexpr (!seqan3::detail::search_traits<configuration_t>::has_output_configuration)
119  return cfg |
120  search_cfg::output_query_id{} |
121  search_cfg::output_reference_id{} |
122  search_cfg::output_reference_begin_position{};
123  else
124  return cfg;
125  }
126 
139  template <typename configuration_t>
140  static auto add_defaults(configuration_t const & cfg)
141  {
142  static_assert(detail::is_type_specialisation_of_v<configuration_t, configuration>,
143  "cfg must be a specialisation of seqan3::configuration.");
144 
145  auto cfg1 = add_default_hit_configuration(cfg);
146  auto cfg2 = add_default_output_configuration(cfg1);
147 
148  return cfg2;
149  }
150 
166  template <typename query_t, typename configuration_t, typename index_t>
167  static auto configure_algorithm(configuration_t const & cfg, index_t const & index)
168  {
169  using query_index_t = std::tuple_element_t<0, query_t>;
170  using search_result_t = typename select_search_result<configuration_t, index_t, query_index_t>::type;
171  using callback_t = std::function<void(search_result_t)>;
172  using type_erased_algorithm_t = std::function<void(query_t, callback_t)>;
173 
174  auto complete_config = cfg | search_cfg::detail::result_type<search_result_t>{};
175  return std::pair{configure_hit_strategy<type_erased_algorithm_t>(complete_config, index), complete_config};
176  }
177 
178  template <typename algorithm_t, typename configuration_t, typename index_t>
179  static algorithm_t configure_hit_strategy(configuration_t const &, index_t const &);
180 
195  template <typename algorithm_t, typename configuration_t, typename index_t>
196  static algorithm_t select_and_return_algorithm(configuration_t const & config, index_t const & index)
197  {
198  using selected_algorithm_t =
199  typename select_search_algorithm<configuration_t,
200  index_t,
201  policy_max_error,
202  policy_search_result_builder<configuration_t>>::type;
203 
204  return selected_algorithm_t{config, index};
205  }
206 };
207 
228 template <typename algorithm_t, typename configuration_t, typename index_t>
229 algorithm_t search_configurator::configure_hit_strategy(configuration_t const & cfg, index_t const & index)
230 {
231  // Delegate to the next config with the modified configuration.
232  auto next_config_step = [&] (auto new_cfg) -> algorithm_t
233  {
234  return select_and_return_algorithm<algorithm_t>(new_cfg, index);
235  };
236 
237  // Check if dynamic config present, otherwise continue.
238  if constexpr (configuration_t::template exists<search_cfg::hit>())
239  {
240  auto hit_variant = get<search_cfg::hit>(cfg).hit_variant;
241 
242  if (std::holds_alternative<empty_type>(hit_variant))
243  throw std::invalid_argument{"The dynamic hit strategy was not initialised! "
244  "Please refer to the configuration documentation of the search algorithm for "
245  "more details."};
246 
247  // Remove dynamic config first.
248  auto cfg_without_hit = cfg.template remove<search_cfg::hit>();
249 
250  // Apply the correct static configuration element.
251  return std::visit(multi_invocable
252  {
253  [&] (search_cfg::hit_all_best) { return next_config_step(cfg_without_hit | search_cfg::hit_all_best{}); },
254  [&] (search_cfg::hit_single_best) { return next_config_step(cfg_without_hit | search_cfg::hit_single_best{}); },
255  [&] (search_cfg::hit_strata const & strata) { return next_config_step(cfg_without_hit | strata); },
256  [&] (auto) { return next_config_step(cfg_without_hit | search_cfg::hit_all{}); }
257  }, hit_variant);
258  }
259  else // Already statically configured.
260  {
261  static_assert(detail::search_traits<configuration_t>::has_hit_configuration,
262  "The hit strategy for the search algorithm was not configured. "
263  "Please refer to the configuration documentation of the search algorithm for more details.");
264 
265  return next_config_step(cfg);
266  }
267 }
268 
269 } // namespace seqan3::detail
Provides the configuration to define the hit strategies "hit_strata", "hit_all", "hit_all_best",...
Provides lazy template instantiation traits.
Provides the configuration for maximum number of errors for all error types.
Provides a type that combines multiple invocables.
Provides the seqan3::detail::policy_max_error.
Provides the seqan3::detail::policy_search_result_builder.
Provides seqan3::search_cfg::detail::result_type.
Provides the configuration for the content of the search result.
Provides seqan3::search_result.
Provides the algorithm to search in an index using search schemes.
Provides type traits for working with templates.
Provides an approximate string matching algorithm based on simple backtracking. This should only be u...
T visit(T... args)