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
function.hpp
Provides various type traits for use on functions.
search_scheme_algorithm.hpp
Provides the algorithm to search in an index using search schemes.
std::pair
policy_max_error.hpp
Provides the seqan3::detail::policy_max_error.
template_inspection.hpp
Provides seqan3::type_list and auxiliary type traits.
std::function
max_error.hpp
Provides the configuration for maximum number of errors for all error types.
search_result.hpp
Provides seqan3::search_result.
policy_search_result_builder.hpp
Provides the seqan3::detail::policy_search_result_builder.
result_type.hpp
Provides seqan3::search_cfg::detail::result_type.
std::invalid_argument
hit.hpp
Provides the configuration to define the hit strategies "hit_strata", "hit_all", "hit_all_best",...
std::visit
T visit(T... args)
std::conditional_t
unidirectional_search_algorithm.hpp
Provides an approximate string matching algorithm based on simple backtracking. This should only be u...
lazy.hpp
Provides lazy template instantiation traits.
output.hpp
Provides the configuration for the content of the search result.
type_list.hpp
Provides seqan3::type_list.