SeqAn3  3.2.0
The Modern C++ library for sequence analysis.
search_configurator.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, 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 =
63 
64  public:
66  using type = search_result<query_id_t, index_cursor_t, reference_id_t, reference_begin_position_t>;
67  };
68 
75  template <typename configuration_t, typename index_t, typename... policies_t>
76  struct select_search_algorithm
77  {
79  using type = lazy_conditional_t<template_specialisation_of<typename index_t::cursor_type, bi_fm_index_cursor>,
80  lazy<search_scheme_algorithm, configuration_t, index_t, policies_t...>,
81  lazy<unidirectional_search_algorithm, configuration_t, index_t, policies_t...>>;
82  };
83 
84 public:
95  template <typename configuration_t>
96  static auto add_default_hit_configuration(configuration_t const & cfg)
97  {
98  if constexpr (!detail::search_traits<configuration_t>::has_hit_configuration)
99  return cfg | search_cfg::hit_all{};
100  else
101  return cfg;
102  }
103 
113  template <typename configuration_t>
114  static auto add_default_output_configuration(configuration_t const & cfg)
115  {
116  if constexpr (!seqan3::detail::search_traits<configuration_t>::has_output_configuration)
117  return cfg | search_cfg::output_query_id{} | search_cfg::output_reference_id{}
118  | search_cfg::output_reference_begin_position{};
119  else
120  return cfg;
121  }
122 
135  template <typename configuration_t>
136  static auto add_defaults(configuration_t const & cfg)
137  {
138  static_assert(detail::is_type_specialisation_of_v<configuration_t, configuration>,
139  "cfg must be a specialisation of seqan3::configuration.");
140 
141  auto cfg1 = add_default_hit_configuration(cfg);
142  auto cfg2 = add_default_output_configuration(cfg1);
143 
144  return cfg2;
145  }
146 
162  template <typename query_t, typename configuration_t, typename index_t>
163  static auto configure_algorithm(configuration_t const & cfg, index_t const & index)
164  {
165  using query_index_t = std::tuple_element_t<0, query_t>;
166  using search_result_t = typename select_search_result<configuration_t, index_t, query_index_t>::type;
167  using callback_t = std::function<void(search_result_t)>;
168  using type_erased_algorithm_t = std::function<void(query_t, callback_t)>;
169 
170  auto complete_config = cfg | search_cfg::detail::result_type<search_result_t>{};
171  return std::pair{configure_hit_strategy<type_erased_algorithm_t>(complete_config, index), complete_config};
172  }
173 
174  template <typename algorithm_t, typename configuration_t, typename index_t>
175  static algorithm_t configure_hit_strategy(configuration_t const &, index_t const &);
176 
191  template <typename algorithm_t, typename configuration_t, typename index_t>
192  static algorithm_t select_and_return_algorithm(configuration_t const & config, index_t const & index)
193  {
194  using selected_algorithm_t =
195  typename select_search_algorithm<configuration_t,
196  index_t,
197  policy_max_error,
198  policy_search_result_builder<configuration_t>>::type;
199 
200  return selected_algorithm_t{config, index};
201  }
202 };
203 
224 template <typename algorithm_t, typename configuration_t, typename index_t>
225 algorithm_t search_configurator::configure_hit_strategy(configuration_t const & cfg, index_t const & index)
226 {
227  // Delegate to the next config with the modified configuration.
228  auto next_config_step = [&](auto new_cfg) -> algorithm_t
229  {
230  return select_and_return_algorithm<algorithm_t>(new_cfg, index);
231  };
232 
233  // Check if dynamic config present, otherwise continue.
234  if constexpr (configuration_t::template exists<search_cfg::hit>())
235  {
236  auto hit_variant = get<search_cfg::hit>(cfg).hit_variant;
237 
238  if (std::holds_alternative<empty_type>(hit_variant))
239  throw std::invalid_argument{"The dynamic hit strategy was not initialised! "
240  "Please refer to the configuration documentation of the search algorithm for "
241  "more details."};
242 
243  // Remove dynamic config first.
244  auto cfg_without_hit = cfg.template remove<search_cfg::hit>();
245 
246  // Apply the correct static configuration element.
247  return std::visit(multi_invocable{[&](search_cfg::hit_all_best)
248  {
249  return next_config_step(cfg_without_hit | search_cfg::hit_all_best{});
250  },
251  [&](search_cfg::hit_single_best)
252  {
253  return next_config_step(cfg_without_hit | search_cfg::hit_single_best{});
254  },
255  [&](search_cfg::hit_strata const & strata)
256  {
257  return next_config_step(cfg_without_hit | strata);
258  },
259  [&](auto)
260  {
261  return next_config_step(cfg_without_hit | search_cfg::hit_all{});
262  }},
263  hit_variant);
264  }
265  else // Already statically configured.
266  {
267  static_assert(detail::search_traits<configuration_t>::has_hit_configuration,
268  "The hit strategy for the search algorithm was not configured. "
269  "Please refer to the configuration documentation of the search algorithm for more details.");
270 
271  return next_config_step(cfg);
272  }
273 }
274 
275 } // 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)