SeqAn3 3.4.0-rc.4
The Modern C++ library for sequence analysis.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
search.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2025 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <algorithm>
13#include <ranges>
14
26
27namespace seqan3::detail
28{
33{
38 template <typename query_t>
39 static void validate_query_type()
40 {
41 using pure_query_t = std::remove_cvref_t<query_t>;
42 if constexpr (range_dimension_v<pure_query_t> == 1u)
43 {
44 static_assert(std::ranges::random_access_range<pure_query_t>,
45 "The query sequence must model random_access_range.");
46 static_assert(std::ranges::sized_range<pure_query_t>, "The query sequence must model sized_range.");
47 }
48 else
49 {
50 static_assert(std::ranges::forward_range<pure_query_t>, "The query collection must model forward_range.");
51 static_assert(std::ranges::sized_range<pure_query_t>, "The query collection must model sized_range.");
52 static_assert(std::ranges::random_access_range<std::ranges::range_value_t<pure_query_t>>,
53 "Elements of the query collection must model random_access_range.");
54 static_assert(std::ranges::sized_range<std::ranges::range_value_t<pure_query_t>>,
55 "Elements of the query collection must model sized_range.");
56 }
57 }
58};
59} // namespace seqan3::detail
60
61namespace seqan3
62{
98template <typename index_t,
99 std::ranges::forward_range queries_t,
100 typename configuration_t = decltype(search_cfg::default_configuration)>
101 requires std::ranges::forward_range<std::ranges::range_reference_t<queries_t>>
102 && std::same_as<range_innermost_value_t<queries_t>, typename index_t::alphabet_type>
103inline auto
104search(queries_t && queries, index_t const & index, configuration_t const & cfg = search_cfg::default_configuration)
105{
106 auto updated_cfg = detail::search_configurator::add_defaults(cfg);
107
108 detail::search_configuration_validator::validate_query_type<queries_t>();
109
110 size_t queries_size = std::ranges::distance(queries);
111 auto indexed_queries = views::zip(std::views::iota(size_t{0}, queries_size), std::forward<queries_t>(queries));
112
113 using indexed_queries_t = decltype(indexed_queries);
114
115 using query_t = std::ranges::range_reference_t<indexed_queries_t>;
116 auto [algorithm, complete_config] = detail::search_configurator::configure_algorithm<query_t>(updated_cfg, index);
117
118 using complete_configuration_t = decltype(complete_config);
120 using algorithm_result_t = typename traits_t::search_result_type;
124
125 // Select the execution handler for the search configuration.
126 auto select_execution_handler = [parallel = complete_config.get_or(search_cfg::parallel{})]()
127 {
128 if constexpr (std::same_as<execution_handler_t, detail::execution_handler_parallel>)
129 {
130 auto thread_count = parallel.thread_count;
131 if (!thread_count)
132 throw std::runtime_error{"You must configure the number of threads in seqan3::search_cfg::parallel."};
133
134 return execution_handler_t{*thread_count};
135 }
136 else
137 {
138 return execution_handler_t{};
139 }
140 };
141
142 // Finally, choose between two way execution returning an algorithm range or calling a user callback on every hit.
143 if constexpr (traits_t::has_user_callback)
144 {
145 select_execution_handler().bulk_execute(algorithm,
146 indexed_queries,
147 get<search_cfg::on_result>(complete_config).callback);
148 }
149 else
150 {
151 using executor_t = detail::algorithm_executor_blocking<indexed_queries_t,
152 decltype(algorithm),
153 algorithm_result_t,
154 execution_handler_t>;
155
156 return algorithm_result_generator_range{executor_t{std::move(indexed_queries),
157 std::move(algorithm),
158 algorithm_result_t{},
159 select_execution_handler()}};
160 }
161}
162
164// Convert query sequence if it does not match the alphabet type of the index.
166template <typename index_t,
167 std::ranges::forward_range queries_t,
168 typename configuration_t = decltype(search_cfg::default_configuration)>
169 requires std::ranges::forward_range<std::ranges::range_reference_t<queries_t>>
170 && (!std::same_as<range_innermost_value_t<queries_t>, typename index_t::alphabet_type>)
171inline auto search(queries_t && queries,
172 index_t const & index,
173 configuration_t const & cfg = search_cfg::default_configuration)
174{
175 static_assert(std::convertible_to<range_innermost_value_t<queries_t>, typename index_t::alphabet_type>,
176 "The alphabet of the text collection must be convertible to the alphabet of the index.");
177
178 if constexpr (range_dimension_v<queries_t> == 2u)
179 return search(queries | views::deep{views::convert<typename index_t::alphabet_type>}, index, cfg);
180 else
181 return search(queries | views::convert<typename index_t::alphabet_type>, index, cfg);
182}
183
184// Overload for a single query (not a collection of queries)
186template <typename index_t,
187 std::ranges::forward_range query_t,
188 typename configuration_t = decltype(search_cfg::default_configuration)>
189inline auto
190search(query_t && query, index_t const & index, configuration_t const & cfg = search_cfg::default_configuration)
191{
192 return search(std::views::single(std::forward<query_t>(query)), index, cfg);
193}
194
196template <typename index_t, typename configuration_t = decltype(search_cfg::default_configuration)>
197inline auto search(char const * const queries,
198 index_t const & index,
199 configuration_t const & cfg = search_cfg::default_configuration)
200{
201 return search(std::string_view{queries}, index, cfg);
202}
203
205template <typename index_t, typename configuration_t = decltype(search_cfg::default_configuration)>
207 index_t const & index,
208 configuration_t const & cfg = search_cfg::default_configuration)
209{
211 query.reserve(std::ranges::size(queries));
212 std::ranges::for_each(queries,
213 [&query](char const * const q)
214 {
215 query.push_back(std::string_view{q});
216 });
217 return search(std::move(query) | std::views::all, index, cfg);
218}
220
221} // namespace seqan3
Provides seqan3::detail::algorithm_executor_blocking.
Provides seqan3::detail::algorithm_result_generator_range.
An input range over the algorithm results generated by the underlying algorithm executor.
Definition algorithm_result_generator_range.hpp:45
A blocking algorithm executor for algorithms.
Definition algorithm_executor_blocking.hpp:60
Handles the parallel execution of algorithms.
Definition execution_handler_parallel.hpp:52
A global configuration type used to enable parallel execution of algorithms.
Definition configuration_element_parallel_mode.hpp:29
static auto add_defaults(configuration_t const &cfg)
Adds default configurations if they were not set by the user.
Definition search_configurator.hpp:133
A wrapper type around an existing view adaptor that enables "deep view" behaviour for that view.
Definition deep.hpp:101
Provides seqan3::configuration and utility functions.
Provides seqan3::views::deep.
Provides the default configuration for the seqan3::search() interface.
T for_each(T... args)
constexpr configuration default_configuration
The default configuration: Compute all exact matches.
Definition default_configuration.hpp:26
auto search(queries_t &&queries, index_t const &index, configuration_t const &cfg=search_cfg::default_configuration)
Search a query or a range of queries in an index.
Definition search.hpp:104
seqan::stl::views::zip zip
A view adaptor that takes several views and returns tuple-like values from every i-th element of each...
Definition zip.hpp:24
The internal SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
Provides seqan3::search_cfg::on_result.
Provides seqan3::search_cfg::parallel configuration.
T push_back(T... args)
T reserve(T... args)
Provides seqan3::detail::search_configurator.
Provides seqan3::detail::search_traits.
Handles the sequential execution of algorithms.
Definition execution_handler_sequential.hpp:31
Class used to validate the search configuration.
Definition search.hpp:33
static void validate_query_type()
Validates the query type to model std::ranges::random_access_range and std::ranges::sized_range.
Definition search.hpp:39
A collection of traits extracted from the search configuration.
Definition search_traits.hpp:31
Provides seqan3::views::convert.
Provides seqan3::views::zip.
Hide me