Loading...
Searching...
No Matches
search.hpp
Go to the documentation of this file.
// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
// SPDX-FileCopyrightText: 2016-2025 Knut Reinert & MPI für molekulare Genetik
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#include <algorithm>
#include <ranges>
#include <seqan3/core/algorithm/algorithm_result_generator_range.hpp>
#include <seqan3/core/algorithm/detail/algorithm_executor_blocking.hpp>
#include <seqan3/core/configuration/configuration.hpp>
#include <seqan3/search/configuration/default_configuration.hpp>
#include <seqan3/search/configuration/on_result.hpp>
#include <seqan3/search/configuration/parallel.hpp>
#include <seqan3/search/detail/search_configurator.hpp>
#include <seqan3/search/detail/search_traits.hpp>
#include <seqan3/utility/views/convert.hpp>
#include <seqan3/utility/views/deep.hpp>
#include <seqan3/utility/views/zip.hpp>
namespace seqan3::detail
{
struct search_configuration_validator
{
template <typename query_t>
static void validate_query_type()
{
using pure_query_t = std::remove_cvref_t<query_t>;
if constexpr (range_dimension_v<pure_query_t> == 1u)
{
static_assert(std::ranges::random_access_range<pure_query_t>,
"The query sequence must model random_access_range.");
static_assert(std::ranges::sized_range<pure_query_t>, "The query sequence must model sized_range.");
}
else
{
static_assert(std::ranges::forward_range<pure_query_t>, "The query collection must model forward_range.");
static_assert(std::ranges::sized_range<pure_query_t>, "The query collection must model sized_range.");
static_assert(std::ranges::random_access_range<std::ranges::range_value_t<pure_query_t>>,
"Elements of the query collection must model random_access_range.");
static_assert(std::ranges::sized_range<std::ranges::range_value_t<pure_query_t>>,
"Elements of the query collection must model sized_range.");
}
}
};
} // namespace seqan3::detail
namespace seqan3
{
template <typename index_t,
std::ranges::forward_range queries_t,
typename configuration_t = decltype(search_cfg::default_configuration)>
requires std::ranges::forward_range<std::ranges::range_reference_t<queries_t>>
&& std::same_as<range_innermost_value_t<queries_t>, typename index_t::alphabet_type>
inline auto
search(queries_t && queries, index_t const & index, configuration_t const & cfg = search_cfg::default_configuration)
{
auto updated_cfg = detail::search_configurator::add_defaults(cfg);
detail::search_configuration_validator::validate_query_type<queries_t>();
size_t queries_size = std::ranges::distance(queries);
auto indexed_queries = views::zip(std::views::iota(size_t{0}, queries_size), std::forward<queries_t>(queries));
using indexed_queries_t = decltype(indexed_queries);
using query_t = std::ranges::range_reference_t<indexed_queries_t>;
auto [algorithm, complete_config] = detail::search_configurator::configure_algorithm<query_t>(updated_cfg, index);
using complete_configuration_t = decltype(complete_config);
using traits_t = detail::search_traits<complete_configuration_t>;
using algorithm_result_t = typename traits_t::search_result_type;
using execution_handler_t = std::conditional_t<complete_configuration_t::template exists<search_cfg::parallel>(),
detail::execution_handler_parallel,
detail::execution_handler_sequential>;
// Select the execution handler for the search configuration.
auto select_execution_handler = [parallel = complete_config.get_or(search_cfg::parallel{})]()
{
if constexpr (std::same_as<execution_handler_t, detail::execution_handler_parallel>)
{
auto thread_count = parallel.thread_count;
if (!thread_count)
throw std::runtime_error{"You must configure the number of threads in seqan3::search_cfg::parallel."};
return execution_handler_t{*thread_count};
}
else
{
return execution_handler_t{};
}
};
// Finally, choose between two way execution returning an algorithm range or calling a user callback on every hit.
if constexpr (traits_t::has_user_callback)
{
select_execution_handler().bulk_execute(algorithm,
indexed_queries,
get<search_cfg::on_result>(complete_config).callback);
}
else
{
using executor_t = detail::algorithm_executor_blocking<indexed_queries_t,
decltype(algorithm),
algorithm_result_t,
execution_handler_t>;
return algorithm_result_generator_range{executor_t{std::move(indexed_queries),
std::move(algorithm),
algorithm_result_t{},
select_execution_handler()}};
}
}
// Convert query sequence if it does not match the alphabet type of the index.
template <typename index_t,
std::ranges::forward_range queries_t,
typename configuration_t = decltype(search_cfg::default_configuration)>
requires std::ranges::forward_range<std::ranges::range_reference_t<queries_t>>
&& (!std::same_as<range_innermost_value_t<queries_t>, typename index_t::alphabet_type>)
inline auto search(queries_t && queries,
index_t const & index,
configuration_t const & cfg = search_cfg::default_configuration)
{
static_assert(std::convertible_to<range_innermost_value_t<queries_t>, typename index_t::alphabet_type>,
"The alphabet of the text collection must be convertible to the alphabet of the index.");
if constexpr (range_dimension_v<queries_t> == 2u)
return search(queries | views::deep{views::convert<typename index_t::alphabet_type>}, index, cfg);
else
return search(queries | views::convert<typename index_t::alphabet_type>, index, cfg);
}
// Overload for a single query (not a collection of queries)
template <typename index_t,
std::ranges::forward_range query_t,
typename configuration_t = decltype(search_cfg::default_configuration)>
inline auto
search(query_t && query, index_t const & index, configuration_t const & cfg = search_cfg::default_configuration)
{
return search(std::views::single(std::forward<query_t>(query)), index, cfg);
}
template <typename index_t, typename configuration_t = decltype(search_cfg::default_configuration)>
inline auto search(char const * const queries,
index_t const & index,
configuration_t const & cfg = search_cfg::default_configuration)
{
return search(std::string_view{queries}, index, cfg);
}
template <typename index_t, typename configuration_t = decltype(search_cfg::default_configuration)>
inline auto search(std::initializer_list<char const * const> const & queries,
index_t const & index,
configuration_t const & cfg = search_cfg::default_configuration)
{
std::vector<std::string_view> query;
query.reserve(std::ranges::size(queries));
std::ranges::for_each(queries,
[&query](char const * const q)
{
query.push_back(std::string_view{q});
});
return search(std::move(query) | std::views::all, index, cfg);
}
} // namespace seqan3
algorithm_executor_blocking.hpp
Provides seqan3::detail::algorithm_executor_blocking.
algorithm_result_generator_range.hpp
Provides seqan3::detail::algorithm_result_generator_range.
algorithm
seqan3::algorithm_result_generator_range
An input range over the algorithm results generated by the underlying algorithm executor.
Definition algorithm_result_generator_range.hpp:45
seqan3::views::deep::deep
deep(underlying_adaptor_t &&inner) -> deep< underlying_adaptor_t >
Template argument deduction helper that preserves lvalue references and turns rvalue references into ...
std::conditional_t
configuration.hpp
Provides seqan3::configuration and utility functions.
deep.hpp
Provides seqan3::views::deep.
default_configuration.hpp
Provides the default configuration for the seqan3::search() interface.
std::forward
T forward(T... args)
seqan3::range_innermost_value_t
typename range_innermost_value< t >::type range_innermost_value_t
Shortcut for seqan3::range_innermost_value (transformation_trait shortcut).
Definition core/range/type_traits.hpp:95
seqan3::range_dimension_v
constexpr size_t range_dimension_v
Returns the number of times you can call seqan3::value_type_t recursively on t (type trait).
Definition core/range/type_traits.hpp:112
seqan3::search_cfg::parallel
seqan3::detail::parallel_mode< std::integral_constant< seqan3::detail::search_config_id, seqan3::detail::search_config_id::parallel > > parallel
Enables the parallel execution of the search algorithm if possible for the given configuration.
Definition parallel.hpp:31
seqan3::search_cfg::default_configuration
constexpr configuration default_configuration
The default configuration: Compute all exact matches.
Definition default_configuration.hpp:26
seqan3::search
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
seqan3::views::zip
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
seqan3::views::convert
constexpr auto convert
A view that converts each element in the input range (implicitly or via static_cast).
Definition utility/views/convert.hpp:66
seqan3
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
seqan3::get
constexpr auto const & get(configuration< configs_t... > const &config) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition configuration.hpp:412
on_result.hpp
Provides seqan3::search_cfg::on_result.
parallel.hpp
Provides seqan3::search_cfg::parallel configuration.
std::vector::push_back
T push_back(T... args)
std::vector::reserve
T reserve(T... args)
std::runtime_error
search_configurator.hpp
Provides seqan3::detail::search_configurator.
search_traits.hpp
Provides seqan3::detail::search_traits.
convert.hpp
Provides seqan3::views::convert.
zip.hpp
Provides seqan3::views::zip.
Hide me