SeqAn3
search_trivial.hpp
Go to the documentation of this file.
1 // ============================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ============================================================================
4 //
5 // Copyright (c) 2006-2018, Knut Reinert & Freie Universitaet Berlin
6 // Copyright (c) 2016-2018, Knut Reinert & MPI Molekulare Genetik
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 // DAMAGE.
32 //
33 // ============================================================================
34 
41 #pragma once
42 
43 #include <type_traits>
44 
45 #include <range/v3/view/drop_exactly.hpp>
46 
47 #include <seqan3/range/concept.hpp>
49 
50 namespace seqan3::detail
51 {
52 
77 template <bool abort_on_hit, typename query_t, typename iterator_t, typename delegate_t>
78 inline bool search_trivial(iterator_t it, query_t & query, typename iterator_t::size_type const query_pos,
79  search_param const error_left, delegate_t && delegate) noexcept(noexcept(delegate))
80 {
81  // Exact case (end of query sequence or no errors left)
82  if (query_pos == query.size() || error_left.total == 0)
83  {
84  // If not at end of query sequence, try searching the remaining suffix without any errors.
85  if (query_pos == query.size() || it.extend_right(ranges::view::drop_exactly(query, query_pos)))
86  {
87  delegate(it);
88  return true;
89  }
90  }
91  // Approximate case
92  else
93  {
94  // Insertion
95  if (error_left.insertion > 0)
96  {
97  search_param error_left2{error_left};
98  error_left2.insertion--;
99  error_left2.total--;
100 
101  // always perform a recursive call. Abort recursion if and only if recursive call found a hit and
102  // abort_on_hit is set to true.
103  if (search_trivial<abort_on_hit>(it, query, query_pos + 1, error_left2, delegate) && abort_on_hit)
104  return true;
105  }
106 
107  // Do not allow deletions at the beginning of the query sequence
108  if (((query_pos > 0 && error_left.deletion > 0) || error_left.substitution > 0) && it.extend_right())
109  {
110  do
111  {
112  // Match (when error_left.substitution > 0) and Mismatch
113  if (error_left.substitution > 0)
114  {
115  bool delta = it.last_char() != query[query_pos];
116  search_param error_left2{error_left};
117  error_left2.total -= delta;
118  error_left2.substitution -= delta;
119 
120  if (search_trivial<abort_on_hit>(it, query, query_pos + 1, error_left2, delegate) && abort_on_hit)
121  return true;
122  }
123 
124  // Deletion (Do not allow deletions at the beginning of the query sequence.)
125  if (query_pos > 0)
126  {
127  // Match (when error_left.substitution == 0)
128  if (error_left.substitution == 0 && it.last_char() == query[query_pos])
129  {
130  if (search_trivial<abort_on_hit>(it, query, query_pos + 1, error_left, delegate) &&
131  abort_on_hit)
132  {
133  return true;
134  }
135  }
136 
137  // Deletions at the end of the sequence are not allowed. This cannot happen: when the algorithm
138  // arrives here, it cannot be at the end of the query and since deletions do not touch the query
139  // (i.e. increase query_pos) it won't be at the end of the query after the deletion.
140  if (error_left.deletion > 0)
141  {
142  search_param error_left2{error_left};
143  error_left2.total--;
144  error_left2.deletion--;
145 
146  if (search_trivial<abort_on_hit>(it, query, query_pos, error_left2, delegate) && abort_on_hit)
147  return true;
148  }
149  }
150  } while (it.cycle_back());
151  }
152  else
153  {
154  // Match (when error_left.substitution == 0)
155  if (it.extend_right(query[query_pos]))
156  {
157  if (search_trivial<abort_on_hit>(it, query, query_pos + 1, error_left, delegate) && abort_on_hit)
158  return true;
159  }
160  }
161  }
162 
163  return false;
164 }
165 
184 template <bool abort_on_hit, typename index_t, typename query_t, typename delegate_t>
185 inline void search_trivial(index_t const & index, query_t & query, search_param const error_left,
186  delegate_t && delegate) noexcept(noexcept(delegate))
187 {
188  search_trivial<abort_on_hit>(index.begin(), query, 0, error_left, delegate);
189 }
190 
192 
193 } // namespace seqan3::detail
Additional non-standard concepts for ranges.
::ranges::iterator_t iterator_t
Alias for ranges::iterator_t. Obtains the iterator type of a range.
Definition: ranges:225
Definition: aligned_sequence_concept.hpp:288
Provides C++20 additions to the type_traits header.
Provides data structures used by different search algorithms.