SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
search_configurator.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 
28 
29 namespace seqan3::detail
30 {
31 
35 class search_configurator
36 {
37 private:
44  template <typename search_configuration_t, typename index_t, typename query_index_t>
45  struct select_search_result
46  {
47  private:
49  using index_cursor_type = typename index_t::cursor_type;
51  using index_size_type = typename index_t::size_type;
53  using traits_type = search_traits<search_configuration_t>;
54 
62  using reference_begin_position_t = std::conditional_t<traits_type::output_reference_begin_position,
63  index_size_type,
64  empty_type>;
65 
66  public:
68  using type = search_result<query_id_t, index_cursor_t, reference_id_t, reference_begin_position_t>;
69  };
70 
77  template <typename configuration_t, typename index_t, typename ...policies_t>
78  struct select_search_algorithm
79  {
81  using type =
82  lazy_conditional_t<bi_fm_index_specialisation<index_t>,
83  lazy<search_scheme_algorithm, configuration_t, index_t, policies_t...>,
84  lazy<unidirectional_search_algorithm, configuration_t, index_t, policies_t...>>;
85  };
86 
87 public:
98  template <typename configuration_t>
99  static auto add_default_hit_configuration(configuration_t const & cfg)
100  {
101  if constexpr (!detail::search_traits<configuration_t>::has_hit_configuration)
102  return cfg | search_cfg::hit_all{};
103  else
104  return cfg;
105  }
106 
116  template <typename configuration_t>
117  static auto add_default_output_configuration(configuration_t const & cfg)
118  {
119  if constexpr (!seqan3::detail::search_traits<configuration_t>::has_output_configuration)
120  return cfg |
121  search_cfg::output_query_id{} |
122  search_cfg::output_reference_id{} |
123  search_cfg::output_reference_begin_position{};
124  else
125  return cfg;
126  }
127 
140  template <typename configuration_t>
141  static auto add_defaults(configuration_t const & cfg)
142  {
143  static_assert(detail::is_type_specialisation_of_v<configuration_t, configuration>,
144  "cfg must be a specialisation of seqan3::configuration.");
145 
146  auto cfg1 = add_default_hit_configuration(cfg);
147  auto cfg2 = add_default_output_configuration(cfg1);
148 
149  return cfg2;
150  }
151 
167  template <typename query_t, typename configuration_t, typename index_t>
168  static auto configure_algorithm(configuration_t const & cfg, index_t const & index)
169  {
170  using query_index_t = std::tuple_element_t<0, query_t>;
171  using search_result_t = typename select_search_result<configuration_t, index_t, query_index_t>::type;
172  using callback_t = std::function<void(search_result_t)>;
173  using type_erased_algorithm_t = std::function<void(query_t, callback_t)>;
174 
175  auto complete_config = cfg | search_cfg::detail::result_type<search_result_t>{};
176  return std::pair{configure_hit_strategy<type_erased_algorithm_t>(complete_config, index), complete_config};
177  }
178 
179  template <typename algorithm_t, typename configuration_t, typename index_t>
180  static algorithm_t configure_hit_strategy(configuration_t const &, index_t const &);
181 
196  template <typename algorithm_t, typename configuration_t, typename index_t>
197  static algorithm_t select_and_return_algorithm(configuration_t const & config, index_t const & index)
198  {
199  using selected_algorithm_t =
200  typename select_search_algorithm<configuration_t,
201  index_t,
202  policy_max_error,
203  policy_search_result_builder<configuration_t>>::type;
204 
205  return selected_algorithm_t{config, index};
206  }
207 };
208 
229 template <typename algorithm_t, typename configuration_t, typename index_t>
230 algorithm_t search_configurator::configure_hit_strategy(configuration_t const & cfg, index_t const & index)
231 {
232  // Delegate to the next config with the modified configuration.
233  auto next_config_step = [&] (auto new_cfg) -> algorithm_t
234  {
235  return select_and_return_algorithm<algorithm_t>(new_cfg, index);
236  };
237 
238  // Check if dynamic config present, otherwise continue.
239  if constexpr (configuration_t::template exists<search_cfg::hit>())
240  {
241  auto hit_variant = get<search_cfg::hit>(cfg).hit_variant;
242 
243  if (std::holds_alternative<empty_type>(hit_variant))
244  throw std::invalid_argument{"The dynamic hit strategy was not initialised! "
245  "Please refer to the configuration documentation of the search algorithm for "
246  "more details."};
247 
248  // Remove dynamic config first.
249  auto cfg_without_hit = cfg.template remove<search_cfg::hit>();
250 
251  // Apply the correct static configuration element.
252  return std::visit(multi_invocable
253  {
254  [&] (search_cfg::hit_all_best) { return next_config_step(cfg_without_hit | search_cfg::hit_all_best{}); },
255  [&] (search_cfg::hit_single_best) { return next_config_step(cfg_without_hit | search_cfg::hit_single_best{}); },
256  [&] (search_cfg::hit_strata const & strata) { return next_config_step(cfg_without_hit | strata); },
257  [&] (auto) { return next_config_step(cfg_without_hit | search_cfg::hit_all{}); }
258  }, hit_variant);
259  }
260  else // Already statically configured.
261  {
262  static_assert(detail::search_traits<configuration_t>::has_hit_configuration,
263  "The hit strategy for the search algorithm was not configured. "
264  "Please refer to the configuration documentation of the search algorithm for more details.");
265 
266  return next_config_step(cfg);
267  }
268 }
269 
270 } // namespace seqan3::detail
Provides various type traits for use on functions.
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 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 seqan3::type_list and auxiliary type traits.
Provides seqan3::type_list.
Provides an approximate string matching algorithm based on simple backtracking. This should only be u...
T visit(T... args)